XPATH觉得没有什么,但*XPATH觉得没有什么,但*(xPath finds nothing b

2019-05-12 08:54发布

这是开始让我反感真正的坏。 我有这样的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节点? 为什么不工作?

谢谢

Answer 1:

我只甩$ 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.movi​​elabs.com/ACNS ”“。 (除非介入的后代有不同的默认命名空间声明,这将阴影在这一个。)

所以,用我的local-name()回答上述忽略的命名空间,或者使用学生支援机构的技术来指定movielabs ACNS,并以此为意。



Answer 2:

你的XML文档的根元素似乎与URI“默认命名空间http://www.movi​​elabs.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文档中使用的一个相匹配。



Answer 3:

使用任何命名空间:

var_dump($newXML->xpath("//*:ID"));


Answer 4:

我不是很精通PHP的XML API,但我怀疑问题出在命名空间。 根据该法的XPath如何工作的,也可能是寻找一个空的命名空间ID元素。 您的ID元素继承从根元素的命名空间。



Answer 5:

你有在文档元素中定义的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]
);

提示:默认命名空间仅用于元素,属性是“无/空命名空间”,除非他们有一个前缀。



文章来源: xPath finds nothing but *