【问题标题】:Find Specific Element Based on an Attribute根据属性查找特定元素
【发布时间】:2011-12-16 04:32:37
【问题描述】:

我一直在回顾我所有的旧代码并尝试对其进行优化。我最近偶然发现并让我难过的事情是试图为此找到一个 xpath 解决方案:

function findit($search) {
    $i=0;
    foreach($xml as $page) { //loop to find specific $element based on $attribute
       if($page['src']==$search) { return $i; }
       $i++;
    }
}

需要返回$i,以便以后可以引用XML中的元素。

这似乎应该是可能的,而且我发现了一些 xpath 字符串,它们看起来应该可以工作,但不能。他们通常引用preceding-children 并通过xpath() 函数对其进行计数,但我再也找不到原始来源,也不知道如何将其转换为 PHP xpath 字符串。

这甚至可能吗?或者它是否比我已经拥有的更好/更快/更有效率?建议/解决方案?

编辑:对于 Tandu 的解决方案

我的 XML 文件示例

<range>
    <page src="attribute1" />
    <page src="attribute2" />
    etc...
    <page src="attribut20" />
</range>

在我当前的 PHP 函数中,$i 总是返回 0,但应该返回找到 $search 的任何位置。已编辑,因此不再需要转换 simplexml。

function findit($search) {
    $dom=new DOMDocument('1.0');
    $dom->load($file);
    $xpath=new DOMXPath($dom);
    $i=$xpath->evaluate("count(/range/page[@src='$search']/preceding-sibling::*)");
    die($dom->saveXML());
}

【问题讨论】:

    标签: php xml xpath


    【解决方案1】:

    使用单个 XPath 表达式,因此您不需要迭代结果

    elementWithSomeName[@attribute = 'someNeededValue']
    

    或(如果“属性是元素的名称”):

    elementWithSomeName[attribute = 'someNeededValue']
    

    【讨论】:

    • 是的,我已经做到了,我正在迭代以便可以在 xml 中找到它的特定位置,因此 $i。不过还是谢谢
    【解决方案2】:

    PHP 至少有两种(据我所知)处理 Xpath 的方法:DOMXPath 库,它与 DOMDocument 一起使用,SimpleXML,它有自己的 xpath() 方法。如果要计算实际表达式(例如在示例中获取 i),则必须使用 DOMXPath::evaluate()SimpleXML::xpath() 只会返回一个节点列表(DOMXPath::query() 也是如此。php 中也有 xpath_ 方法,但这些似乎是其他方法的功能版本,仍然需要 DOM 上下文节点对象。

    我不确定上面示例中的 xml 是什么,但下面的示例使用 DOMXPath。据我所知,没有简单的方法可以将SimpleXML 转换为DOMDocument。您只需要单独加载 xml。

    $xml = <<<XML
       <root>
          <child attribute="one" />
          <child attribute="one" />
          <child attribute="one" />
          <child attribute="one" />
          <child attribute="one" />
          <child attribute="two" />
          <child attribute="one" />
          <child attribute="one" />
          <child attribute="one" />
          <child attribute="one" />
          <child attribute="one" />
       </root>
    XML;
    $dom = new DOMDocument;
    $dom->loadXML($xml);
    //DOMXPath requires DOMDocument in its constructor
    $xpath = new DOMXPath($dom);
    //evaluate will return types .. we are expecting an int, not a DOMNodeList
    //Look for a child node of root named "child" with attribute="two"
    //Count all its preceding siblings.
    $i = $xpath->evaluate('count(/root/child[@attribute="two"]/preceding-sibling::*)');
    

    【讨论】:

    • 用simplexml这么久都忘了他哥哥dom了!
    • *没有意识到 enter 会添加注释而不是移动到下一行 XD 我的 XML 当然是 simplexml。这就是我所拥有的,不确定是否是最优雅的方式,但我仍然无法让它工作:(在原始帖子中添加了代码,因为我无法在此处正确格式化:(
    • @showerhead 我可以看到你的 xml 吗?请注意,“root”和“child”是节点名称。例如,如果您改为使用&lt;father&gt;&lt;son /&gt;&lt;/father&gt;,则在我的示例中,您可以将“root”替换为“father”,将“child”替换为“son”。我看到您在问题的示例中仍然使用“孩子”。
    • 是的,当我在我的代码中实现它时我改变了它,然后当我问这个问题时又回来了。这是一个精简版本或我的 XML: 这是我使用的 xpath "count(//page[@src='$ search']/preceding-sibling::*)" 也尝试了 "count(/range/page[@src='$search']/preceding-sibling::*)" 都无济于事。还摆弄在 php 变量处和周围使用不同的引号,因为我知道 php 是如何挑剔的。我知道 $dom 正在打印出来,因为我的函数中的 die() 打印了我的目标文档的克隆。
    • 如果&lt;page&gt; 是列表中的第一个元素,那么获得零是否有意义?你检查过$search的值吗?
    猜你喜欢
    • 2017-04-10
    • 2023-03-29
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 2014-09-14
    相关资源
    最近更新 更多