如何通过路径检索特定XML节点的值?

时间:2010-12-21 01:23:00

标签: javascript xml xpath

我正在寻找解决此问题的Javascript解决方案:

我有一个XML文档,它是通过典型的AJAX方法加载的:

var xml = http.responseXML;

请考虑以下示例xml片段:

<main>
    <primary>
         <enabled>true</enabled>
     </primary>
     <secondary>
         <enabled>true</enabled>
     </secondary>
 </main>

我想通过指定路径来获取节点的值,如下所示:

var second_enabled = getNodeValueByPath('main/secondary/enabled', xml);

我找不到这样做的简洁方法。在使用getElementsByTagName之后,我似乎被迫迭代节点集合。

我如何构建方法getNodeValueByPath或者Javascript中是否有一些允许这样做的构造?

我不熟悉Javascript。

编辑:以下示例显示了我尝试使用XPath及其失败的方法:

XML:

<?xml version="1.0" ?>
<main xmlns="example.com">
  <primary>
    <enabled>true</enabled>
  </primary>
  <secondary>
    <enabled>false</enabled>
  </secondary>
</main>

JavaScript:(这些只是相关功能)

function useHttpResponse()
{
    if (http.readyState == 4)
    {
        if(http.status == 200)
        {
            var xml = http.responseXML;
            var evalue = getXMLValueByPath('/main/secondary/enabled', xml);
            alert(evalue);
        }
    }
}

function getXMLValueByPath(nodepath, xml)
{
    var result = xml.evaluate(nodepath, xml, null, XPathResult.STRING_TYPE, null).stringValue;
    return result;
}

我使用上面的JavaScript而没有任何额外的库。我正在使用Mozilla Firefox 3.6.13,它使用document.evaluate方法来选择节点(根据this information from w3schools)。 此应用程序供内部使用,不必在多个浏览器上运行。

鉴于这些示例,将出现警告对话框,但不包含任何文本。如果我从XML文档中删除字符串xmlns="example.com",则会出现警告对话框,其中包含所需的文本“false”。

使用Firebug进行调试,只要声明了名称空间,resultNode就是一个空字符串。

4 个答案:

答案 0 :(得分:5)

这是FAQ:在XPath 1.0中,没有前缀的QName测试选择null(或空)命名空间URI下的元素。因此,您需要从输入源(example.com)注册默认命名空间URI的前缀。

你如何使用DOM 3 XPath API做到这一点?

来自http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathEvaluator-evaluate

  

evaluate
  评估XPath   表达式字符串并返回结果   如果可能的话,指定类型   的参数
  [...]
  resolver 类型 XPathNSResolver
  解析器允许所有翻译   前缀,包括xml   名称空间前缀,在XPath中   表达到适当的命名空间   的URI。如果将其指定为null,   中的任何名称空间前缀   表达将导致   DOMException被抛出   代码NAMESPACE_ERR

来自https://developer.mozilla.org/en/DOM/document.evaluate

var xpathResult = document.evaluate(
 xpathExpression, 
 contextNode, 
 namespaceResolver, 
 resultType, 
 result);
     
      
  • namespaceResolver是一个将传递任何名称空间前缀的函数,并且应该返回表示名称空间URI的字符串   与该前缀相关联。它会   用于解析其中的前缀   XPath本身,以便它们可以   与文件相匹配。 null是   常见的HTML文档或没有   使用名称空间前缀。
  •   

完成此guide后,您可以使用document.createNSResolverfunction之类的内容:

function nsResolver(prefix) {   
  return prefix == 'ex' ? 'example.com' : null;   
}  

function useHttpResponse()
{
  if (http.readyState == 4)
  {
     if (http.status == 200)
     {
        var xml = http.responseXML;
        var evalue = xml.evaluate('string(/ex:main/ex:secondary/ex:enabled)',
                                  xml,
                                  nsResolver,
                                  XPathResult.STRING_TYPE,
                                  null);
        alert(evalue.stringValue);
     }
  }
}     

答案 1 :(得分:1)

我一直在玩同样的东西,我尝试了一些XPath JS库,这里有一个:http://js-xpath.sourceforge.net/,但是说了这些,我无法得到工作所以我会看到这个狂热地提问:)

另外,在SO:Cross-browser XPath implementation in JavaScript

答案 2 :(得分:1)

var xpathtosearchfor = '//div';
var result = new XPathEvaluator().evaluate(xpathtosearchfor,
    document.documentElement, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);

至少在firefox中

答案 3 :(得分:-2)

XmlDocument xDoc = new XmlDocument();
xDoc.Load("d:\\one.xml");
XmlNode xNode = xDoc.SelectSingleNode(@"//main/secondary/enabled");
string result = ((XmlElement)xNode).FirstChild.Value;