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

时间:2022-07-02 02:40:14

I am looking for a Javascript solution to this problem:

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

I have an XML document which is loaded by way of a typical AJAX method:

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

var xml = http.responseXML;

var xml = http.responseXML;

Consider the following example xml snippet:

请考虑以下示例xml片段:

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

I would like to get the value of a node by specifying the path as follows:

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

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

I cannot find any concise way of doing something like this. I seem to be forced to iterate through node collections after using getElementsByTagName and the like.

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

How would I construct the method getNodeValueByPath or is there some construct in Javascript that allows for this?

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

I am not well versed in Javascript.

我不熟悉Javascript。

EDIT: Here is an example that shows my attempt at using XPath and how it is failing:

编辑:这是一个示例,显示我尝试使用XPath及其失败的方式:

XML:

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

JavaScript: (these are the relevant functions only)

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;
}

I am using the above JavaScript without any additional libraries. I am using Mozilla Firefox 3.6.13 which uses the document.evaluate method to select nodes (according to this information from w3schools). This application is for internal use and does not have to work on multiple browsers.

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

Given these examples, the alert dialog will appear, but contain no text. If I remove the string xmlns="example.com" from the XML document, the alert dialog appears with the text "false" as desired.

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

Debugging using Firebug shows that resultNode is an empty string as long as the namespace is declared.

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

4 个解决方案

#1


5  

This is FAQ: In XPath 1.0, a QName test without prefix selects elements under the null (or empty) namespace URI. So you need to register a prefix to the default namespace URI from your input source (example.com).

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

How do you do that with DOM 3 XPath API?

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

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

evaluate
Evaluates an XPath expression string and returns a result of the specified type if possible.
Parameters
[...]
resolver of type XPathNSResolver
The resolver permits translation of all prefixes, including the xml namespace prefix, within the XPath expression into appropriate namespace URIs. If this is specified as null, any namespace prefix within the expression will result in DOMException being thrown with the code NAMESPACE_ERR.

evaluate评估XPath表达式字符串,并在可能的情况下返回指定类型的结果。 XPathNSResolver类型的参数[...]解析器解析器允许将XPath表达式中的所有前缀(包括xml名称空间前缀)转换为适当的名称空间URI。如果将其指定为null,则表达式中的任何名称空间前缀都将导致使用代码NAMESPACE_ERR抛出DOMException。

And from https://developer.mozilla.org/en/DOM/document.evaluate

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

var xpathResult = document.evaluate(
 xpathExpression, 
 contextNode, 
 namespaceResolver, 
 resultType, 
 result);
  • namespaceResolver is a function that will be passed any namespace prefixes and should return a string representing the namespace URI associated with that prefix. It will be used to resolve prefixes within the XPath itself, so that they can be matched with the document. null is common for HTML documents or when no namespace prefixes are used.
  • namespaceResolver是一个将传递任何名称空间前缀的函数,并且应该返回一个表示与该前缀关联的名称空间URI的字符串。它将用于解析XPath本身内的前缀,以便它们可以与文档匹配。 null是常见的HTML文档或没有使用名称空间前缀。

Following this guide, you can use document.createNSResolver or a function like:

按照本指南,您可以使用document.createNSResolver或类似的函数:

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);
     }
  }
}     

#2


1  

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

In firefox at least

至少在firefox中

#3


1  

I've been playing around with the same thing, I tried a few XPath JS libraries, here's one: http://js-xpath.sourceforge.net/, but having said that, I couldn't get stuff working so I'll be watching this question avidly :)

我一直在玩同样的东西,我尝试了一些XPath JS库,这里有一个:http://js-xpath.sourceforge.net/,但话虽如此,我无法让东西工作所以我'热切地看着这个问题:)

Also, at SO: Cross-browser XPath implementation in JavaScript

此外,在SO:JavaScript中的跨浏览器XPath实现

#4


-2  

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

#1


5  

This is FAQ: In XPath 1.0, a QName test without prefix selects elements under the null (or empty) namespace URI. So you need to register a prefix to the default namespace URI from your input source (example.com).

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

How do you do that with DOM 3 XPath API?

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

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

evaluate
Evaluates an XPath expression string and returns a result of the specified type if possible.
Parameters
[...]
resolver of type XPathNSResolver
The resolver permits translation of all prefixes, including the xml namespace prefix, within the XPath expression into appropriate namespace URIs. If this is specified as null, any namespace prefix within the expression will result in DOMException being thrown with the code NAMESPACE_ERR.

evaluate评估XPath表达式字符串,并在可能的情况下返回指定类型的结果。 XPathNSResolver类型的参数[...]解析器解析器允许将XPath表达式中的所有前缀(包括xml名称空间前缀)转换为适当的名称空间URI。如果将其指定为null,则表达式中的任何名称空间前缀都将导致使用代码NAMESPACE_ERR抛出DOMException。

And from https://developer.mozilla.org/en/DOM/document.evaluate

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

var xpathResult = document.evaluate(
 xpathExpression, 
 contextNode, 
 namespaceResolver, 
 resultType, 
 result);
  • namespaceResolver is a function that will be passed any namespace prefixes and should return a string representing the namespace URI associated with that prefix. It will be used to resolve prefixes within the XPath itself, so that they can be matched with the document. null is common for HTML documents or when no namespace prefixes are used.
  • namespaceResolver是一个将传递任何名称空间前缀的函数,并且应该返回一个表示与该前缀关联的名称空间URI的字符串。它将用于解析XPath本身内的前缀,以便它们可以与文档匹配。 null是常见的HTML文档或没有使用名称空间前缀。

Following this guide, you can use document.createNSResolver or a function like:

按照本指南,您可以使用document.createNSResolver或类似的函数:

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);
     }
  }
}     

#2


1  

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

In firefox at least

至少在firefox中

#3


1  

I've been playing around with the same thing, I tried a few XPath JS libraries, here's one: http://js-xpath.sourceforge.net/, but having said that, I couldn't get stuff working so I'll be watching this question avidly :)

我一直在玩同样的东西,我尝试了一些XPath JS库,这里有一个:http://js-xpath.sourceforge.net/,但话虽如此,我无法让东西工作所以我'热切地看着这个问题:)

Also, at SO: Cross-browser XPath implementation in JavaScript

此外,在SO:JavaScript中的跨浏览器XPath实现

#4


-2  

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