所选节点中的SimpleXML xpath

时间:2016-01-28 15:12:35

标签: php xml xpath simplexml

我有以下XML文件

<Item> 
  <name>...</name>
  <id>...</id>   
  <ImageSets>    
    <ImageSet Category="variant">
      <SwatchImage>
        <URL>...</URL>
        <Height Units="pixels"></Height>
        <Width Units="pixels"></Width>
      </SwatchImage>
      <SmallImage>
        <URL>...</URL>
        <Height Units="pixels"></Height>
        <Width Units="pixels"></Width>
      </SmallImage>
    </ImageSet>

    <ImageSet Category="primary">
      <SwatchImage>
        <URL>...</URL>
        <Height Units="pixels"></Height>
        <Width Units="pixels"></Width>
      </SwatchImage>
      <SmallImage>
        <URL>...</URL>
        <Height Units="pixels"></Height>
        <Width Units="pixels"></Width>
      </SmallImage>
    </ImageSet>
  </ImageSets>
</Item>

<Item>....</Item>

然后我使用PHP迭代文件中的Item节点。

foreach ($Xml as $item){
    $name = $item->name;
    $ID = $item->id;
};

等等。该代码可以完美地为每个项目提取名称和ID。

现在我的问题是提取ImageSet Category ='primary' - &gt; SmallImage-&gt; URL。 ImageSet节点不按任何特定顺序排列,因此有时“主要”将是第一个,有时是“变体”,这就是$item->ImageSets->ImageSet[1]不是解决方案的原因

所以在我的主foreach循环中,我尝试使用xpath,如下所示:

$src='';    
foreach ($item->ImageSets->xpath('//ImageSet[@Category="primary"]') as $img){
    $src = $img->MediumImage->URL;
};

绝对没有运气。

任何想法都会受到赞赏。

2 个答案:

答案 0 :(得分:2)

实现你的上下文节点$ item(我毫不怀疑你需要那个上下文节点的原因;-))你正在寻找一个图像集a)是ImageSets的子节点(它又是你的直接子节点)上下文节点)和b)具有值为primary的属性Category(您已正确编码)

<?php
$itemset = new SimpleXMLElement(data());
foreach ($itemset as $item) { // or something else - just some reason why you have to work with $item
    foreach ($item->xpath('ImageSets/ImageSet[@Category="primary"]') as $p) {
        echo $p->SwatchImage->URL;
    }
}


function data() {
    return <<< eox
<ItemSet>
    <Item>
      <name>...</name>
      <id>...</id>
      <ImageSets>
        <ImageSet Category="variant">
          <SwatchImage>
            <URL>...</URL>
            <Height Units="pixels"></Height>
            <Width Units="pixels"></Width>
          </SwatchImage>
          <SmallImage>
            <URL>...</URL>
            <Height Units="pixels"></Height>
            <Width Units="pixels"></Width>
          </SmallImage>
        </ImageSet>
        <ImageSet Category="primary">
          <SwatchImage>
            <URL>primary swatch image url</URL>
            <Height Units="pixels"></Height>
            <Width Units="pixels"></Width>
          </SwatchImage>
          <SmallImage>
            <URL>...</URL>
            <Height Units="pixels"></Height>
            <Width Units="pixels"></Width>
          </SmallImage>
        </ImageSet>
      </ImageSets>
    </Item>
    <Item>...</Item>
</ItemSet>      
eox;
}

答案 1 :(得分:1)

XPath表达式中有错误。如果表达式以/开头,则它与文档本身相关。您希望它相对于当前节点。这意味着您有两种可能的解决方案

ImageSet[@Category="primary"]

这会扩展为child::ImageSet。它获取作为上下文节点的直接子节点的ImageSet元素节点。

.//ImageSet[@Category="primary"]

扩展并标准化为descendant::ImageSet。它在当前上下文中获取任何ImageSet,即使它不是直接子项。 .表示当前节点,//将轴更改为后代。