在foreach循环中重复相同结果的xpath

时间:2011-10-07 13:20:46

标签: php xml xpath

我使用以下代码解析XML文件,没有问题:

 foreach ($xml->product as $products) {

 $title = $products->name; etc etc

但是,由于XML的结构,我必须在其中一个节点上使用xpath,我需要确保它返回正确的数据

 $actors = $xml->xpath("//property[name[. ='Actors']]/value");

 $actor = $actors[0];

这很好但是它总是返回XML文件的第一条记录,我需要它来跟上循环,如果这是有道理的。

我尝试了以下但是同样的事情发生了:

 $actors = $products->xpath("//property[name[. ='Actors']]/value");

这是有问题的xml,但是我上面的例子使用了一个名为name的节点,它有数据Actors,交换格式,你有同样的想法,因为下面有一个节点

<name>Format</name>


<properties>
 <group>
  <name>Product</name>
   <property>
    <id>48546006</id>
    <name>Product name</name>
    <value>JOLLY PHONICS (JOLLY PHONICS S.)</value>
   </property>
 </group>
 <group>
  <name>Product properties</name>
   <property>
    <id>43560296</id>
    <name>Product Title</name>
    <value>JOLLY PHONICS (JOLLY PHONICS S.)</value>
   </property>
   <property>
    <id>43560292</id>
     <name>Format</name>
     <value>DVD</value>
    </property>
   </group>
</properties>

这里是我正在使用的完整foreach循环(我省略了一些,因为你不需要阅读所有正常工作的东西,如你所见:

foreach ($xml->product as $products) { // AA

    $title = $products->name;

    $PRid = $products->id;

    $actors = $xml->xpath("//property[./name[.='Actors']]/value[next()]"); // this ok but repeats

$actors = $actors[0];

$genre = $xml->xpath("//property[name[. ='Genre']]/value"); 

$genre = $genre[0];

$prodcat = $products->{'category'};

    $addline = mysql_query("
    insert into dbname(
    blah blah
    )
        VALUES (
    blah blah
    ) ON DUPLICATE KEY UPDATE lowprice='$lowprice', highprice='$highprice'",$db);
    if(!$addline) { echo "cannot add to table here".mysql_error(); exit; } // debug

foreach ($xml->product->retailer as $retailer) { // BB

    this is another foreach loop but works perfectly

} // close BB
} // close AA

所以,问题是 - 我需要提取XML文件中的节点,这些节点总是在名为property的节点内,但是,我不能简单地使用例如name [2]因为它们有时在不同的地方 - 所以建议我使用xpath从我需要的特定节点获取数据,因为它更精确 - 而问题是它工作正常但是由于某种原因不会只需从当前节点获取数据,但是我尝试./或.//,它总是从第一个节点返回数据。

有什么想法吗?

3 个答案:

答案 0 :(得分:0)

我相信以下内容适合您。在xpath中使用./是指当前节点,而不是//作为根节点:

$actors = $products->xpath("./property[name[. ='Actors']]/value");

您的XML结构可能需要稍加修改,我们无法看到。但关键的一点是使用./

<强> UDPATE

根据this question,尝试:

$actors = $products->xpath("./property/value[../name/text() = 'Actors']");

答案 1 :(得分:0)

在xpath中,以'//'开头表示从根开始的后代或自我。您可能想尝试添加“。”到当前节点开始。

$string = file_get_contents('sampleFromPost.xml');
$xml = simplexml_load_string($string);

$groups = $xml->group;
foreach($groups as $group) {
    // Changed Actors to Product Title, since Actors doesn't exist in sample.

    $title = $group->xpath('.//property[name="Product Title"]/value');
    // -- or --
    $title = $group->xpath('.//property/value[../name="Product Title"]');

    // do something with the value
    var_dump($title);
}

答案 2 :(得分:0)

我怀疑(在您发布PHP代码之前)。您不在循环体中使用相对路径。当然,这总是产生相同的(即绝对的)结果。

您必须使用XPath 引用$product(不是$xml)并且使用相对路径,如下所示:

foreach ($xml->product as $product) { // AA
  $title   = $product->name;
  $PRid    = $product->id;
  $actors  = $product->xpath(".//property[name='Actors']/value");
  $genre   = $product->xpath(".//property[name='Genre']/value");
  $prodcat = $product->{'category'};

  $addline = mysql_query("
    insert into dbname(
      blah blah
    )
    VALUES (
      blah blah
    ) ON DUPLICATE KEY UPDATE lowprice='$lowprice', highprice='$highprice'", $db
  );

  if(!$addline) { 
    echo "cannot add to table here".mysql_error(); exit; // debug
  }

  foreach ($xml->product->retailer as $retailer) { // BB
    this is another foreach loop but works perfectly
  } // close BB
} // close AA

PS:你真的想在 AA循环中运行BB循环(或者你真的想在这里循环$product->retailer)吗?