Reputation: 11
I have the following XML file, and I would like to know the exact number of occurences the tag "ing" is present in each "ing-div" node. It will help me to determine the number of ingredients present for each ingredient title (i.e. FRUIT has 4 ingredients, Sponge Cake has 4 ingredients,...). Any suggestions?
<?xml version="1.0" encoding="UTF-8"?>
<recipeml version="0.5">
<recipe>
<head>
<title>1,000 Calorie-A-Bite Trifle</title>
<categories>
<cat>Desserts</cat>
<cat>Usenet</cat></categories>
<yield>1</yield></head>
<ingredients>
<ing-div>
<title>FRUIT</title>
<ing>
<amt>
<qty>3</qty>
<unit/></amt>
<item>Pears</item></ing>
<ing>
<amt>
<qty>8</qty>
<unit>ounces</unit></amt>
<item>Raspberries (tinned or fresh)</item></ing>
<ing>
<amt>
<qty>1</qty>
<unit/></amt>
<item>Passion fruit</item></ing>
<ing>
<amt>
<qty/>
<unit/></amt>
<item>Dry sherry (1 bottle)</item></ing></ing-div>
<ing-div>
<title>SPONGE CAKE</title>
<ing>
<amt>
<qty>1/2</qty>
<unit>cups</unit></amt>
<item>Butter</item></ing>
<ing>
<amt>
<qty>10</qty>
<unit>tablespoons</unit></amt>
<item>Sugar, castor</item></ing>
<ing>
<amt>
<qty>1 1/4</qty>
<unit>cups</unit></amt>
<item>Flour, self-raising</item></ing>
<ing>
<amt>
<qty>2</qty>
<unit/></amt>
<item>Eggs (slightly whisked)</item></ing></ing-div>
<ing-div>
<title>CUSTARD</title>
<ing>
<amt>
<qty>2</qty>
<unit/></amt>
<item>Eggs</item></ing>
<ing>
<amt>
<qty>1</qty>
<unit>pinch</unit></amt>
<item>Salt</item></ing>
<ing>
<amt>
<qty>1</qty>
<unit>pinch</unit></amt>
<item>Nutmeg</item></ing>
<ing>
<amt>
<qty>10</qty>
<unit>ounces</unit></amt>
<item>Double cream (or use whipping cream)</item></ing></ing-div>
<ing-div>
<title>TOPPING</title>
<ing>
<amt>
<qty>10</qty>
<unit>ounces</unit></amt>
<item>Double cream</item></ing>
<ing>
<amt>
<qty/>
<unit/></amt>
<item>Roast almonds</item></ing></ing-div></ingredients>
<directions>
<step> Peel and slice pears, drain raspberries if tinned, and scoop out passion
fruit. Place fruit in large trifle bowl and add an ample quantity of
sherry. Leave for twenty-four hours to soak in the refrigerator.
Preheat oven to 350 degrees F. Cream butter and sugar until light and
fluffy. Add eggs and about 2 T of flour and beat. Fold in rest of flour.
Bake in 7-inch square tin for 25-30 mins until brown. Let cool. Slice into
fingers and arrange on top of fruit. More sherry may be added at this
point.
Pour one large glass of sherry. Mix eggs and add all ingredients to small
bowl. Place bowl in pan of simmering water. Stir continuously with wooden
spoon, sipping sherry, until custard thickens. This takes about ten
minutes. Pour custard on top of sponge. Chill in fridge. Whip cream until
stiff and smooth over top of custard. Arrange almonds decoratively.
NOTES:
* The title says it all -- This recipe is my own invention.
: Difficulty: moderate
: Time: 1 hour preparation, 1 day waiting, 10 minutes cooking.
: Precision: no need to measure.
: Angi Lamb
: Department of Computer Science, University of York, UK
: ukc!minster!angi
: Copyright (C) 1986 USENET Community Trust
From Gemini's MASSIVE MealMaster collection at www.synapse.com/~gemini
</step></directions></recipe></recipeml>
Upvotes: 1
Views: 345
Reputation: 82018
DomDocument has a function JUST FOR THAT!
How to use getElementsByTagName:
$doc = new DOMDocument();
$doc->load(<xml>);
foreach( $doc->getElementsByTagName('ing') as $tag )
{
// to iterate the children
foreach( $tag->childNodes as $child )
{
// outputs the xml of the child nodes. Of course, there are any number of
// things that you could do instead!
echo $doc->saveXML($child);
}
}
Upvotes: 1
Reputation: 5520
function unserialize_xml($input, $callback = null, $recurse = false){
$data = ((!$recurse) && is_string($input))? simplexml_load_string($input): $input;
if ($data instanceof SimpleXMLElement) $data = (array) $data;
if (is_array($data)) foreach ($data as &$item) $item = unserialize_xml($item, $callback, true);
return (!is_array($data) && is_callable($callback))? call_user_func($callback, $data): $data;
}
send the XML string to this function and check the results which are now an array which is easy to work with:
foreach($result['recipe'] as $recipe){
echo $recipe['title'].' - '.count($recipe['ingredients']['ing']);
}
EDIT:
just add an iterator for your while loop
$xml = new DOMDocument();
$xml->load(path/to/file);
$xpath = new DOMXPath($xml);
$ingdiv = $xpath->query("/recipeml/recipe/ingredients/ing-div");
$length = $ingdiv->length;
$key=0;
// iterate over all <ing-div> from last to first
while($key<$length) {
// number of <ing> in the specific <ing-div>
print $xpath->query("ing", $ingdiv->item($key))->length;
$key++
}
Upvotes: 1
Reputation: 5062
Look at using Xpath with DOMXPath::query. You can then could the number of results produced by the query.
php > $doc = new DOMDocument();
php > $doc->preserveWhiteSpace = false;
php > $doc->Load("/tmp/test.xml");
php > $xpath = new DOMXPath($doc);
php > $query = "//ing";
php > $ingredients = $xpath->query($query);
php > echo $ingredients->length;
int(14)
You may need to modify the Xpath query to suit your needs.
Upvotes: 1