这是开始让我反感真正的坏。 我有这样的XML代码:
更新了正确的命名空间
<?xml version="1.0" encoding="utf-8"?>
<Infringement xsi:schemaLocation="http://www.movielabs.com/ACNS http://www.movielabs.com/ACNS/ACNS2v1.xsd" xmlns="http://www.movielabs.com/ACNS" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Case>
<ID>...</ID>
<Status>Open</Status>
</Case>
<Complainant>
<Entity>...</Entity>
<Contact>...</Contact>
<Address>...</Address>
<Phone>...</Phone>
<Email>...</Email>
</Complainant>
<Service_Provider>
<Entity>...</Entity>
<Address></Address>
<Email>...</Email>
</Service_Provider>
<Source>
<TimeStamp>...</TimeStamp>
<IP_Address>...</IP_Address>
<Port>...</Port>
<DNS_Name></DNS_Name>
<Type>...</Type>
<UserName></UserName>
<Number_Files>1</Number_Files>
<Deja_Vu>No</Deja_Vu>
</Source>
<Content>
<Item>
<TimeStamp>...</TimeStamp>
<Title>...</Title>
<FileName>...</FileName>
<FileSize>...</FileSize>
<URL></URL>
</Item>
</Content>
</Infringement>
而这个PHP代码:
<?php
$data = urldecode($_POST["xml"]);
$newXML = simplexml_load_string($data);
var_dump($newXML->xpath("//ID"));
?>
我只甩$ newXML,并得到吨的数据,但我已经运行的唯一的XPath传回任何东西,但一个空数组是“*”
是不是“// ID”应该找到文档中的所有ID节点? 为什么不工作?
谢谢
我只甩$ newXML,并得到吨的数据,但我已经运行的唯一的XPath传回任何东西,但一个空数组是“*”
那么从返回var_dump($newXML->xpath("*"));
? <Infringement>
?
如果问题是命名空间,试试这个:
var_dump($newXML->xpath("//*[local-name() = 'ID']"));
这将他的名字是“ID”的文件中匹配任何元素,无论命名空间。
我的东西的作品,如果我用“NS”全部替换“的xmlns”
等等,什么? 你确定你向我们展示了文档中所有的xmlns相关的属性?
更新:此问题已编辑以表明XML确实有一个默认的命名空间声明。 这也解释了原来的问题:你的XPath表达式选择ID元素都没有命名空间,但是你的文档中的元素是采用MovieLabs ACNS命名空间,多亏了默认命名空间声明。
声明xmlns="http://www.movielabs.com/ACNS"
的元件上是指“这个元件和所有后代不具有一个命名空间前缀(如ID)是在由命名空间URI“表示的命名空间HTTP ://www.movielabs.com/ACNS ”“。 (除非介入的后代有不同的默认命名空间声明,这将阴影在这一个。)
所以,用我的local-name()
回答上述忽略的命名空间,或者使用学生支援机构的技术来指定movielabs ACNS,并以此为意。
你的XML文档的根元素似乎与URI“默认命名空间http://www.movielabs.com/ACNS ”。 这意味着,你的文档中的所有元素都属于该命名空间。 问题是,没有命名空间前缀的所有XPath表达式正在寻找不属于任何命名空间的元素。 要搜索的元素(或属性...)从某一个命名空间,你需要的命名空间URI注册一些前缀,然后在你的XPath表达式使用这个前缀。
在PHP中的SimpleXML的情况下,它做了这样的事情
$newXML = simplexml_load_string($data);
$newXML->registerXPathNamespace('prefix', 'http://www.movielabs.com/ACNS');
var_dump($newXML->xpath("//prefix:ID"));
prefix
可以为几乎任何文字,但空间URI必须与您的XML文档中使用的一个相匹配。
使用任何命名空间:
var_dump($newXML->xpath("//*:ID"));
我不是很精通PHP的XML API,但我怀疑问题出在命名空间。 根据该法的XPath如何工作的,也可能是寻找一个空的命名空间ID元素。 您的ID元素继承从根元素的命名空间。
你有在文档元素中定义的XML命名空间(所述xmlns="http://www.movielabs.com/ACNS"
属性)。 该命名空间是URL http://www.movielabs.com/ACNS
。 这必须通过一个全球唯一的字符串(URN)。 由于该网址经常被使用。 有人使用您的域命名空间的机会是非常低的,你可以在URL把一些文档。
XML解析器解析的命名空间。 的节点获得4种性质。
对于<Infringement xmlns="http://www.movielabs.com/ACNS"/>
$namespaceURI => http://www.movielabs.com/ACNS
$localName => Infringement
$prefix =>
$nodeName => Infringement
对于<movie:Infringement xmlns:movie="http://www.movielabs.com/ACNS"/>
$namespaceURI => http://www.movielabs.com/ACNS
$localName => Infringement
$prefix => movie
$nodeName => movie:Infringement
$namespaceURI
和$localName
是稳定的。 另外两个取决于前缀。 前缀是命名空间的别名。 命名空间URI是长期和复杂的,它将使XML很多更难看了,如果每个元素/属性用来写。 但是你可以解释元素节点,如:
{http://www.movielabs.com/ACNS}:Infringement
所以命名空间的一两件事,它定义了节点的意思是,没有前缀/别名。 前缀可以一个子元件上重新定义。
<foo xmlns="urn:foo"><bar xmlns="urn:bar"/></foo>
XPath使用与自己的解析器相同的概念。 您注册自己的前缀命名空间。 所以没关系的前缀是如何在XML中,只有URI必须匹配的命名空间。
在DOM这样做的DOMXPath实例:
$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);
$xpath->registerNamespace('movie', 'http://www.movielabs.com/ACNS');
var_dump(
$xpath->evaluate('string(/movie:Infringement/movie:Case/movie:ID)')
);
SimpleXML中,你可以注册上的SimpleXMLElement的命名空间。
$element = simplexml_load_string($xml);
$element->registerXpathNamespace('movie', 'http://www.movielabs.com/ACNS');
var_dump(
(string)$element->xpath('/movie:Infringement/movie:Case/movie:ID')[0]
);
提示:默认命名空间仅用于元素,属性是“无/空命名空间”,除非他们有一个前缀。