下面我有一个
PHP脚本,我需要搜索XML文件并找到< AnotherChild>的ID.出于某种原因,目前它返回0结果,我无法弄清楚原因.如果有人能看出为什么它会返回0结果我真的很感激它,如果他们能让我知道为什么.
XML:
<TransXChange xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.transxchange.org.uk/" xsi:schemaLocation="http://www.transxchange.org.uk/ http://www.transxchange.org.uk/schema/2.1/TransXChange_general.xsd" CreationDateTime="2013-07-12T18:12:21.8122032+01:00" ModificationDateTime="2013-07-12T18:12:21.8122032+01:00" Modification="new" RevisionNumber="3" FileName="swe_44-611A-1-y10.xml" SchemaVersion="2.1"> <Node1>...</Node1> <Node2>...</Node2> <Node3>...</Node3> <Node4>...</Node4> <Node5>...</Node5> <Node6>...</Node6> <Node7> <Child> <id>ABCDEFG123</id> </Child> <AnotherChild> <id>ABCDEFG124</id> </AnotherChild> </Node7> <Node8>...</Node8> </TransXChange>
PHP:
<?PHP $xmldoc = new DOMDocument(); $xmldoc->load("directory1/directory2/file.xml"); $xpathvar = new DOMXPath($xmldoc); $xpathvar->registerNamespace('transXchange','http://www.transxchange.org.uk/'); $queryResult = $xpathvar->query('//AnotherChild/id'); foreach($queryResult as $result) { echo $result->textContent; } ?>
谢谢
在评论中链接的两个问题实际上回答了这个问题,但他们并没有明确说明为什么他们回答IMO,所以我将在
my answer in chat之后添加这个.
原文链接:https://www.f2er.com/php/130957.html请考虑以下XML文档:
<root> <child> <grandchild>foo</grandchild> </child> </root>
它根本没有xmlns属性,这意味着您可以查询//孙子并获得您期望的结果.每个节点都在默认命名空间中,因此无需在XPath中注册命名空间即可解决所有问题.
现在考虑一下:
<root xmlns="http://www.bar.com/"> <child> <grandchild>foo</grandchild> </child> </root>
这声明了http://www.bar.com/的命名空间,因此您必须使用该命名空间来寻址成员节点.
正如您已经想到的那样,执行此操作的方法是使用DOMXPath::registerNamespace()
– 但您错过的关键点是(在PHP的XPath实现中)每个命名空间必须使用前缀注册,并且您必须使用该前缀来寻址节点属于它.在XPath中使用空前缀注册命名空间是不可能的.
因此,鉴于上面的第二个例子,让我们看看我们将如何执行原始的//孙子查询:
<?PHP $doc = new DOMDocument(); $doc->loadXML($xml); $xpath = new DOMXPath($doc); $xpath->registerNamespace('bar','http://www.bar.com/'); $nodes = $xpath->query('//bar:grandchild'); foreach($nodes as $node) { // do stuff with $node }
请注意我们如何使用它的URI注册命名空间,并指定了前缀.即使原始XML不包含此前缀,我们在查询中使用前缀 – example.
要了解原因,让我们看看另一段XML:
<baz:root xmlns:baz="http://www.bar.com/"> <baz:child> <baz:grandchild>foo</baz:grandchild> </baz:child> </baz:root>
该文档在语义上与第二个文档相同 – 代码示例与其中任何一个(proof)同样适用.前缀与命名空间分开.请注意,即使在文档中使用baz:前缀,XPath也会使用bar:前缀.这是因为标识命名空间的思路是URI,而不是前缀.
因此,当文档使用命名空间时,我们必须使用命名空间而不是反对它,方法是在XPath中注册命名空间并使用我们注册的前缀来引用属于该命名空间的任何节点.
为了完整起见,当我们将这些原则应用于您的原始文档时,您将与问题中的代码一起使用的查询是:
//transXchange:AnotherChild/transXchange:id