当前位置: 首页 > 知识库问答 >
问题:

XPath如何处理XML命名空间?

谭玄天
2023-03-14

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。但如果有多个名称空间,事情可能会变得糟糕。

共有2个答案

诸葛品
2023-03-14

我使用/*[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不起作用。

司空俊雅
2023-03-14

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)
  • 另请参见:Java XPath:带有默认名称空间xmlns的查询

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/“。请告