XPath 1.0/2.0
在XPath中定义命名空间(推荐)
XPath本身没有将命名空间前缀与命名空间绑定的方法。这些功能由托管库提供。
建议使用这些功能并定义命名空间前缀,然后根据需要用于限定XML元素和属性名称。
这里列出了XPath主机提供的一些不同机制,用于指定命名空间前缀绑定到命名空间URI。
(原始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);
谷歌文档:
不幸的是,IMPORTXML()
不提供命名空间前缀绑定机制。请参见下一节,击败XPath中的命名空间,了解如何使用 local-name()
作为解决方法。
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";
}
});
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 );
请注意,如果默认命名空间有一个关联的命名空间前缀定义,使用
Document.createNSResolver()
返回的
nsResolver()
可以避免需要自定义
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 (ElementTree):
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改编而来:
$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命名空间的经典问答。
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.NET:
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
XPath中击败命名空间(不推荐)
另一种方法是编写测试local-name()
的谓词:
/*[local-name()='IntuitResponse']/*[local-name()='QueryResponse']
或者,在XPath 2.0中:
/*:IntuitResponse/*:QueryResponse
使用这种方式绕过命名空间是可行的,但并不推荐,因为它
Under-specifies the full element/attribute name.
Fails to differentiate between element/attribute names in different
namespaces (the very purpose of namespaces). Note that this concern could be addressed by adding an additional predicate to check the namespace URI explicitly:
/*[ namespace-uri()='http://schema.intuit.com/finance/v3'
and local-name()='IntuitResponse']
/*[ namespace-uri()='http://schema.intuit.com/finance/v3'
and local-name()='QueryResponse']
Thanks to Daniel Haley for the namespace-uri()
note.
Is excessively verbose.
XPath 3.0/3.1
支持现代XPath 3.0/3.1的库和工具允许在XPath表达式中直接指定命名空间URI:
/Q{http://schema.intuit.com/finance/v3}IntuitResponse/Q{http://schema.intuit.com/finance/v3}QueryResponse
虽然
Q{http://schema.intuit.com/finance/v3}
比使用XML命名空间前缀更冗长,但它具有独立于托管库的命名空间前缀绑定机制的优点。
Q {}
符号被称为
Clark符号,以其发起者James Clark命名。 W3C XPath 3.1 EBNF语法将其称为
BracedURILiteral
。
感谢Michael Kay提出涵盖XPath 3.0 / 3.1的BracedURILiteral
的建议。
javax.xml.xpath.XPath
。我同意在在线测试器中它不起作用是令人困惑的事情之一。 - Adam