【问题标题】:SimpleXML xpath within selected node选定节点内的 SimpleXML xpath
【发布时间】:2016-01-28 15:12:35
【问题描述】:

我有以下 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'->SmallImage->URL。 ImageSet 节点不按任何特定顺序排列,因此有时“主要”会在前,有时会出现“变体”,这就是 $item-&gt;ImageSets-&gt;ImageSet[1] 不是解决方案的原因

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

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

绝对没有运气。

任何想法都将不胜感激。

【问题讨论】:

    标签: php xml xpath simplexml


    【解决方案1】:

    与您的上下文节点 $item 相关(我毫不怀疑这就是您需要该上下文节点的原因 ;-))您正在寻找的 ImageSet 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;
    }
    

    【讨论】:

    • 很好的解决方案,但是我找到了另一个: foreach ($item->ImageSets->ImageSet as $img){ foreach ($img->attributes() as $a=>$b ){ if ($b == 'primary'){ $src = $img->MediumImage->URL;回声 $src; } } };只是想知道哪个更快?
    • 性能->不要猜测,但要衡量。但我有一种预感,在脚本“内部”进行迭代和比较会更快。
    【解决方案2】:

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

    ImageSet[@Category="primary"]

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

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

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

    【讨论】:

      猜你喜欢
      • 2011-01-27
      • 2012-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多