如何计算php中给定节点的子元素的出现次数?

时间:2011-06-23 23:27:52

标签: php xml

我有以下XML文件,我想知道每个“ing-div”节点中标记“ing”出现的确切数量。它将帮助我确定每种成分标题的成分数量(即FRUIT有4种成分,Sponge Cake有4种成分,......)。有什么建议吗?

<?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>

3 个答案:

答案 0 :(得分:1)

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;
}

将XML字符串发送到此函数并检查结果,这些结果现在是一个易于使用的数组:

foreach($result['recipe'] as $recipe){
  echo $recipe['title'].' - '.count($recipe['ingredients']['ing']);
}

编辑:

只需为while循环添加一个迭代器

$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++ 
}

答案 1 :(得分:1)

DomDocument有一个函数JUST FOR THAT

如何使用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);
    }
}

答案 2 :(得分:1)

使用带有DOMXPath::query的Xpath。然后,您可以查询查询产生的结果数量。

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)

您可能需要修改Xpath查询以满足您的需求。