XPath如何处理XML命名空间?
如果我使用
/IntuitResponse/QueryResponse/Bill/Id
为了解析下面的XML文档,我得到了0个节点。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<IntuitResponse xmlns="http://schema.intuit.com/finance/v3"
time="2016-10-14T10:48:39.109-07:00">
<QueryResponse startPosition="1" maxResults="79" totalCount="79">
<Bill domain="QBO" sparse="false">
<Id>=1</Id>
</Bill>
</QueryResponse>
</IntuitResponse>
但是,我没有在XPath中指定名称空间(即http://schema.intuit.com/finance/v3
不是路径的每个标记的前缀)。如果我没有明确告诉XPath,它怎么知道我想要哪个Id
?我认为在这种情况下(因为只有一个名称空间),XPath可以完全忽略xmlns
。但如果有多个名称空间,事情可能会变得糟糕。
我使用/*[name()='...']
在谷歌表中从维基数据中获取一些计数。我有一个这样的表
thes WD prop links items
NOM P7749 3925 3789
AAT P1014 21157 20224
cols链接
和项目
中的公式是
=IMPORTXML("https://query.wikidata.org/sparql?query=SELECT(COUNT(*)as?c){?item wdt:"&$B14&"[]}","//*[name()='literal']")
=IMPORTXML("https://query.wikidata.org/sparql?query=SELECT(COUNT(distinct?item)as?c){?item wdt:"&$B14&"[]}","//*[name()='literal']")
分别地SPARQL查询碰巧没有任何空格。。。
我看到在Xml命名空间中使用了name()
而不是local-name()
破坏了我的xpath!,并且由于某种原因//*: litald
不起作用。
XPath本身没有将名称空间前缀与名称空间绑定的方法。这些设施由托管图书馆提供。
建议您使用这些工具并定义名称空间前缀,然后根据需要使用这些前缀来限定XML元素和属性名称。
下面是XPath主机为指定命名空间URI的命名空间前缀绑定提供的一些不同机制。
(OP最初的XPath,/IntuitResponse/QueryResponse/Bill/Id
,已被省略为/IntuitResponse/QueryResponse
)
C#:
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("i", "http://schema.intuit.com/finance/v3");
XmlNodeList nodes = el.SelectNodes(@"/i:IntuitResponse/i:QueryResponse", nsmgr);
Java(SAX):
NamespaceSupport support = new NamespaceSupport();
support.pushContext();
support.declarePrefix("i", "http://schema.intuit.com/finance/v3");
Java(XPath):
xpath.setNamespaceContext(new NamespaceContext() {
public String getNamespaceURI(String prefix) {
switch (prefix) {
case "i": return "http://schema.intuit.com/finance/v3";
// ...
}
});
DocumentBuilderFactory。setNamespaceAware(true)
JavaScript:
请参见实现用户定义的命名空间解析器:
function nsResolver(prefix) {
var ns = {
'i' : 'http://schema.intuit.com/finance/v3'
};
return ns[prefix] || null;
}
document.evaluate( '/i:IntuitResponse/i:QueryResponse',
document, nsResolver, XPathResult.ANY_TYPE,
null );
请注意,如果默认名称空间定义了关联的名称空间前缀,请使用文档返回的
可以免除客户的需求nsResolver()
。createNSResolver()nsResolver()
。
Perl(LibXML):
my $xc = XML::LibXML::XPathContext->new($doc);
$xc->registerNs('i', 'http://schema.intuit.com/finance/v3');
my @nodes = $xc->findnodes('/i:IntuitResponse/i:QueryResponse');
Python(lxml):
from lxml import etree
f = StringIO('<IntuitResponse>...</IntuitResponse>')
doc = etree.parse(f)
r = doc.xpath('/i:IntuitResponse/i:QueryResponse',
namespaces={'i':'http://schema.intuit.com/finance/v3'})
元素树(Python):
namespaces = {'i': 'http://schema.intuit.com/finance/v3'}
root.findall('/i:IntuitResponse/i:QueryResponse', namespaces)
Python(Scrapy):
response.selector.register_namespace('i', 'http://schema.intuit.com/finance/v3')
response.xpath('/i:IntuitResponse/i:QueryResponse').getall()
PhP:
根据@Tomalak使用DOMDocument的回答改编:
php prettyprint-override">$result = new DOMDocument();
$result->loadXML($xml);
$xpath = new DOMXpath($result);
$xpath->registerNamespace("i", "http://schema.intuit.com/finance/v3");
$result = $xpath->query("/i:IntuitResponse/i:QueryResponse");
另请参见@IMSoP关于PHP SimpleXML名称空间的规范Q/A。
Ruby(Nokogiri):
puts doc.xpath('/i:IntuitResponse/i:QueryResponse',
'i' => "http://schema.intuit.com/finance/v3")
请注意,Nokogiri支持删除名称空间,
doc.remove_namespaces!
但是请参阅下面的警告,以阻止破坏XML命名空间。
VBA:
xmlNS = "xmlns:i='http://schema.intuit.com/finance/v3'"
doc.setProperty "SelectionNamespaces", xmlNS
Set queryResponseElement =doc.SelectSingleNode("/i:IntuitResponse/i:QueryResponse")
VB。净:
xmlDoc = New XmlDocument()
xmlDoc.Load("file.xml")
nsmgr = New XmlNamespaceManager(New XmlNameTable())
nsmgr.AddNamespace("i", "http://schema.intuit.com/finance/v3");
nodes = xmlDoc.DocumentElement.SelectNodes("/i:IntuitResponse/i:QueryResponse",
nsmgr)
SoapUI(文档):
declare namespace i='http://schema.intuit.com/finance/v3';
/i:IntuitResponse/i:QueryResponse
xmlstarlet:
-N i="http://schema.intuit.com/finance/v3"
XSLT:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:i="http://schema.intuit.com/finance/v3">
...
一旦声明了名称空间前缀,就可以编写XPath来使用它:
/i:IntuitResponse/i:QueryResponse
另一种方法是编写谓词来测试local-name()
:
/*[local-name()='IntuitResponse']/*[local-name()='QueryResponse']
或者,在XPath 2.0中:
/*:IntuitResponse/*:QueryResponse
以这种方式绕过名称空间是可行的,但不建议这样做,因为它
>
低于指定完整的元素/属性名称。
无法区分不同命名空间中的元素/属性名称(命名空间的目的)。请注意,可以通过添加额外的谓词来显式检查命名空间URI1来解决这个问题:
/*[ namespace-uri()='http://schema.intuit.com/finance/v3'
and local-name()='IntuitResponse']
/*[ namespace-uri()='http://schema.intuit.com/finance/v3'
and local-name()='QueryResponse']
1感谢Daniel Haley提供的名称空间-uri()
注释。
太冗长了。
问题内容: 我花了整整一天的时间尝试从以下文档中提取一个XML节点,并且无法掌握XML命名空间的细微差别以使其正常工作。 XML文件总的来说很大,所以这是与我有关的部分: 该文档继续进行,并且从头到尾都井井有条。我正在尝试从“ documentnbr”标签(底部的三个)中提取“ number”属性。 我用于执行此操作的代码如下所示: 其中QUERY_FORM_NUMBER是我的XPath表达式,而
主要内容:命名冲突,使用前缀来避免命名冲突,XML 命名空间 - xmlns 属性,统一资源标识符(URI,全称 Uniform Resource Identifier),默认的命名空间,实际使用中的命名空间XML 命名空间提供避免元素命名冲突的方法。 命名冲突 在 XML 中,元素名称是由开发者定义的,当两个不同的文档使用相同的元素名时,就会发生命名冲突。 这个 XML 携带 HTML 表格的信息: <table> <tr> <td>Apples</td> <td>Bananas</td> <
以下来自维基百科关于XML命名空间的文章: 使用保留的XML属性xmlns或xmlns:前缀声明XML命名空间,其值必须是有效的命名空间名称。 例如,以下声明将“xhtml:”前缀映射到xhtml命名空间: xhtml=”http://www.w3.org/1999/xhtml" 本文暗示上述声明创建了一个名为“XTHML”的名称空间。URL如何“http://www.w3.org/1999/xh
本文向大家介绍xpath 示例XML(无名称空间),包括了xpath 示例XML(无名称空间)的使用技巧和注意事项,需要的朋友参考一下 示例 这是一些示例XML,可以针对这些XML编写示例XPath:
XML信封命名空间的正确URI是什么。我见过很多,例如。”http://www.w3.org/2001/12/soap-envelope“,”http://www.w3.org/2001/06/soap-envelope“,”http://www.w3.org/2003/05/soap-envelope“,”http://schemas.xmlsoap.org/soap/envelope/“。请告