/*************************************************************************** * Copyright (C) 2003 by * * Richard Lärkäng * * * * Copyright (C) 2003-2005 by * * Jason Kivlighn (jkivlighn@gmail.com) * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * ***************************************************************************/ #include "recipemlimporter.h" #include #include #include #include #include "datablocks/recipe.h" #include "datablocks/mixednumber.h" RecipeMLImporter::RecipeMLImporter() : BaseImporter() {} void RecipeMLImporter::parseFile( const TQString& file ) { TQFile input( file ); if ( input.open( IO_ReadOnly ) ) { TQDomDocument doc; TQString error; int line; int column; if ( !doc.setContent( &input, &error, &line, &column ) ) { setErrorMsg( TQString( i18n( "\"%1\" at line %2, column %3. This may not be a RecipeML file." ) ).arg( error ).arg( line ).arg( column ) ); return ; } TQDomElement recipeml = doc.documentElement(); if ( recipeml.tagName() != "recipeml" ) { setErrorMsg( i18n( "This file does not appear to be a valid RecipeML archive." ) ); return ; } TQDomNodeList l = recipeml.childNodes(); for ( unsigned i = 0 ; i < l.count(); i++ ) { TQDomElement el = l.item( i ).toElement(); TQString tagName = el.tagName(); if ( tagName == "meta" ) continue; else if ( tagName == "recipe" ) readRecipemlRecipe( el ); else if ( tagName == "menu" ) readRecipemlMenu( el ); else kdDebug() << "Unknown tag within : " << tagName << endl; } } else setErrorMsg( i18n( "Unable to open file." ) ); } RecipeMLImporter::~RecipeMLImporter() {} void RecipeMLImporter::readRecipemlRecipe( const TQDomElement& recipe_element ) { recipe.empty(); TQDomNodeList l = recipe_element.childNodes(); for ( unsigned i = 0; i < l.count(); i++ ) { TQDomElement el = l.item( i ).toElement(); TQString tagName = el.tagName(); if ( tagName == "head" ) readRecipemlHead( el ); else if ( tagName == "ingredients" ) readRecipemlIngs( el ); else if ( tagName == "directions" ) readRecipemlDirections( el ); else if ( tagName == "description" ) {} //TODO: what do we do with this? else if ( tagName == "equipment" ) {} //TODO: what do we do with this? else if ( tagName == "nutrition" ) {} //TODO: what do we do with this? else if ( tagName == "diet-exchanges" ) {} //TODO: what do we do with this? else kdDebug() << "Unknown tag within : " << el.tagName() << endl; } add ( recipe ); } void RecipeMLImporter::readRecipemlHead( const TQDomElement& head ) { TQDomNodeList l = head.childNodes(); for ( unsigned i = 0 ; i < l.count(); i++ ) { TQDomElement el = l.item( i ).toElement(); TQString tagName = el.tagName(); if ( tagName == "title" ) recipe.title = el.text().stripWhiteSpace(); else if ( tagName == "subtitle" ) recipe.title += ": " + el.text().stripWhiteSpace(); else if ( tagName == "version" ) {} //TODO: what do we do with this? else if ( tagName == "source" ) readRecipemlSrcItems( el ); else if ( tagName == "categories" ) { TQDomNodeList categories = el.childNodes(); for ( unsigned j = 0; j < categories.count(); j++ ) { TQDomElement c = categories.item( j ).toElement(); if ( c.tagName() == "cat" ) { recipe.categoryList.append( Element( c.text() ) ); } } } else if ( tagName == "description" ) recipe.instructions += "\n\nDescription: " + el.text().stripWhiteSpace(); else if ( tagName == "preptime" ) readRecipemlPreptime( el ); else if ( tagName == "yield" ) { TQDomNodeList yieldChildren = el.childNodes(); for ( unsigned j = 0; j < yieldChildren.count(); j++ ) { TQDomElement y = yieldChildren.item( j ).toElement(); TQString tagName = y.tagName(); if ( tagName == "range" ) readRecipemlRange( y, recipe.yield.amount, recipe.yield.amount_offset ); else if ( tagName == "unit" ) recipe.yield.type = y.text(); else kdDebug() << "Unknown tag within : " << y.tagName() << endl; } } else kdDebug() << "Unknown tag within : " << el.tagName() << endl; } } void RecipeMLImporter::readRecipemlIngs( const TQDomElement& ings ) { TQDomNodeList l = ings.childNodes(); for ( unsigned i = 0 ; i < l.count(); i++ ) { TQDomElement el = l.item( i ).toElement(); TQString tagName = el.tagName(); if ( tagName == "ing" ) readRecipemlIng( el ); else if ( tagName == "ing-div" ) //NOTE: this can have the "type" attribute { TQString header; TQDomNodeList ingDiv = el.childNodes(); for ( unsigned j = 0; j < ingDiv.count(); j++ ) { TQDomElement cEl = ingDiv.item( j ).toElement(); if ( cEl.tagName() == "title" ) header = cEl.text().stripWhiteSpace(); else if ( cEl.tagName() == "description" ) {} //TODO: what do we do with this? else if ( cEl.tagName() == "ing" ) readRecipemlIng( cEl, 0, header ); else if ( tagName == "note" ) {} //TODO: what do we do with this? else kdDebug() << "Unknown tag within : " << cEl.tagName() << endl; } } else if ( tagName == "note" ) {} //TODO: what do we do with this? else kdDebug() << "Unknown tag within : " << el.tagName() << endl; } } void RecipeMLImporter::readRecipemlIng( const TQDomElement& ing, Ingredient *ing_parent, const TQString &header ) { Ingredient new_ing; TQDomNodeList ingChilds = ing.childNodes(); TQString name, unit, size, prep_method; Ingredient quantity; quantity.amount = 1;// default quantity assumed by RecipeML DTD for ( unsigned j = 0; j < ingChilds.count(); j++ ) { TQDomElement ingChild = ingChilds.item( j ).toElement(); TQString tagName = ingChild.tagName(); if ( tagName == "amt" ) { TQDomNodeList amtChilds = ingChild.childNodes(); for ( unsigned k = 0; k < amtChilds.count(); k++ ) { TQDomElement amtChild = amtChilds.item( k ).toElement(); if ( amtChild.tagName() == "qty" ) readRecipemlTQty( amtChild, quantity ); else if ( amtChild.tagName() == "size" ) size = amtChild.text().stripWhiteSpace(); else if ( amtChild.tagName() == "unit" ) unit = amtChild.text().stripWhiteSpace(); else kdDebug() << "Unknown tag within : " << amtChild.tagName() << endl; } } else if ( tagName == "item" ) { name = ingChild.text().stripWhiteSpace(); if ( ing.attribute( "optional", "no" ) == "yes" ) prep_method = "(optional)"; } else if ( tagName == "prep" ) { //FIXME: this overwrite the optional attribute prep_method = ingChild.text().stripWhiteSpace(); } else if ( tagName == "alt-ing" ) readRecipemlIng( ingChild, &new_ing, header ); else kdDebug() << "Unknown tag within : " << ingChild.tagName() << endl; } if ( !size.isEmpty() ) unit.prepend( size + " " ); new_ing.name = name; new_ing.units = Unit( unit, quantity.amount+quantity.amount_offset ); new_ing.amount = quantity.amount; new_ing.amount_offset = quantity.amount_offset; new_ing.group = header; new_ing.prepMethodList = ElementList::split(",",prep_method); if ( !ing_parent ) recipe.ingList.append(new_ing); else ing_parent->substitutes.append( new_ing ); } void RecipeMLImporter::readRecipemlDirections( const TQDomElement& dirs ) { TQDomNodeList l = dirs.childNodes(); TQStringList directions; for ( unsigned i = 0 ; i < l.count(); i++ ) { TQDomElement el = l.item( i ).toElement(); if ( el.tagName() == "step" ) directions.append( el.text().stripWhiteSpace() ); else kdDebug() << "Unknown tag within : " << el.tagName() << endl; } TQString directionsText; if ( directions.count() > 1 ) { for ( unsigned i = 1; i <= directions.count(); i++ ) { if ( i != 1 ) { directionsText += "\n\n"; } TQString sWith = TQString( "%1. " ).arg( i ); TQString text = directions[ i - 1 ]; if ( !text.stripWhiteSpace().startsWith( sWith ) ) directionsText += sWith; directionsText += text; } } else directionsText = directions[ 0 ]; recipe.instructions = directionsText; } void RecipeMLImporter::readRecipemlMenu( const TQDomElement& menu_el ) { TQDomNodeList l = menu_el.childNodes(); for ( unsigned i = 0 ; i < l.count(); i++ ) { TQDomElement el = l.item( i ).toElement(); TQString tagName = el.tagName(); if ( tagName == "head" ) readRecipemlHead( el ); else if ( tagName == "description" ) {} //TODO: what do we do with this? else if ( tagName == "recipe" ) readRecipemlRecipe( el ); else kdDebug() << "Unknown tag within : " << tagName << endl; } } void RecipeMLImporter::readRecipemlSrcItems( const TQDomElement& sources ) { TQDomNodeList l = sources.childNodes(); for ( unsigned i = 0 ; i < l.count(); i++ ) { TQDomElement srcitem = l.item( i ).toElement(); TQString tagName = srcitem.tagName(); if ( tagName == "srcitem" ) recipe.authorList.append( Element( srcitem.text().stripWhiteSpace() ) ); else kdDebug() << "Unknown tag within : " << tagName << endl; } } void RecipeMLImporter::readRecipemlPreptime( const TQDomElement &preptime ) { TQDomNodeList l = preptime.childNodes(); for ( unsigned i = 0 ; i < l.count(); i++ ) { TQDomElement el = l.item( i ).toElement(); TQString tagName = el.tagName(); if ( tagName == "time" ) { int qty = 0; TQString timeunit; TQDomNodeList time_l = el.childNodes(); for ( unsigned i = 0 ; i < time_l.count(); i++ ) { TQDomElement time_el = time_l.item( i ).toElement(); TQString time_tagName = time_el.tagName(); if ( time_tagName == "qty" ) qty = time_el.text().toInt(); else if ( time_tagName == "timeunit" ) timeunit = time_el.text(); else kdDebug() << "Unknown tag within