xpath внутри цикла foreach, повторяя тот же результат - PullRequest
4 голосов
/ 07 октября 2011

Я использую следующий код для синтаксического анализа 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, поменяйте его на Format, и у вас возникнет та же идея, что и под узлом, который находится под

<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, которые мне нужно извлечь, которые всегда находятся внутри узла, называемого свойством, но я не могу просто использовать, например, name [2], поскольку они иногда находятся в разных местах - поэтому предлагается использовать xpath для получения данных от нужного мне узла, поскольку он более точен - и проблема в том, что он работает нормально, но по какой-то причине не будет просто получить данные из текущего узла, однако я пытаюсь ./ или .//, он всегда возвращает данные из первого узла.

Есть идеи?

Ответы [ 3 ]

0 голосов
/ 07 октября 2011

В 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);
}
0 голосов
/ 07 октября 2011

Как я и подозревал (до того, как вы опубликовали свой код PHP).Вы не используете относительные пути в теле цикла.Конечно, это всегда дает один и тот же (то есть абсолютный) результат.

Вы должны ссылаться на $product (не $xml) с вашим XPath и , используя относительный путь оттуда,как это:

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: Вы действительно хотите запустить цикл BB в цикле АА (или вы действительно хотите зациклить $product->retailer здесь)?

0 голосов
/ 07 октября 2011

Я считаю, что следующее должно работать для вас. Использование ./ в xpath относится к текущему узлу, а не // в качестве корневого узла:

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

Может потребоваться небольшая модификация вашей XML-структуры, которую мы не видим. Но ключ на вынос использует ./

UDPATE

На основании этого вопроса , попробуйте:

$actors = $products->xpath("./property/value[../name/text() = 'Actors']");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...