如何在 XML 树中找到值的节点位置? [英] How to find the node position of a value in an XML tree?

查看:33
本文介绍了如何在 XML 树中找到值的节点位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据我在页面上输入的值,我想检索相关的 XML 数据.

Based on a value I input on the page, I want to retrieve the relevant XML data.

例如,如果我从页面上的 datalist 输入字段中输入/选择 option "Michigan",我想找到 node 密歇根在 XML 文档中的位置.通过知道node的位置,我可以从对应Michigan的XML文档中检索其他信息,例如GDPPOPULATION>.

For example, if I input/select option "Michigan" from the datalist input field on my page, I want to find the node position of Michigan in the XML document. By knowing the node position, I can retrieve other information from the XML document corresponding to Michigan such as GDP and POPULATION.

我知道我应该将 [1] 更改为诸如 [i] 之类的变量,但是我应该如何对函数进行编码?

I know I should change [1] to a variable such as [i], but how should I code the function?

var n = document.getElementById("myInputId");
n.addEventListener("keyup", function(event) {
  event.preventDefault();
  if (event.keyCode === 13) {
    document.getElementById("myButton").click();
  }
});

function loadXMLDoc() {
  var xmlhttp = new XMLHttpRequest();
  xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
      myFunction(xmlhttp);
    }
  };
  xmlhttp.open("GET", "state_data.xml", true);
  xmlhttp.send();
}

function myFunction(xml) {
  var x, i, xmlDoc;
  xmlDoc = xml.responseXML;
  x = xmlDoc.getElementsByTagName("UNIT")
  var s = xmlDoc.getElementsByTagName("STATE")[1].childNodes[0].nodeValue;
  document.getElementById("state").innerHTML = s;
  var gElem = xmlDoc.getElementsByTagName("GDP");
  var g = (gElem.length > 0) ? gElem[1].childNodes[0].nodeValue : "";
  document.getElementById("gdp").innerHTML = g;
  var pElem = xmlDoc.getElementsByTagName("POPULATION");
  var p = (pElem.length > 0) ? pElem[1].childNodes[0].nodeValue : "";
  document.getElementById("population").innerHTML = p;

  var a = n.value
  document.getElementById("inputValue").innerHTML = a;
  xmlDoc.UNITs.forEach(function(e, z) {
    var q = document.getElementById("inputValue").innerHTML;
    if (e.properties.id == q) {
      document.getElementById("nodePosition").innerHTML = z;
    }
  });
}

<body onload="loadXMLDoc()">
  <input list="myInput" id="myInputId" value="">
  <button id="myButton" onClick="loadXMLDoc()">submit</button>

  <p>input value: <span id="inputValue"></span></p>
  <p>XML tree node position of input value: <span id="nodePosition"></span></p>
  <p>State: <span id="state"></span></p>
  <p>GDP: <span id="gdp"></span></p>
  <p>Population: <span id="population"></span></p>

  <datalist id="myInput">
<option id="AL">Alabama</option>
<option id="CA">California</option>
<option id="MI">Michigan</option>
<option id="TX">Texas</option>
<option id="WI">Wisconsin</option>
</datalist>

这是我的 XML:

<?xml version="1.0" encoding="UTF-8"?>
<STATE_DATA>
 <UNIT>
    <STATE>Wisconsin</STATE>
    <GDP>232,300,000,000</GDP>
    <POPULATION>5,800,000</POPULATION>
 </UNIT>
 <UNIT>
    <STATE>Alabama</STATE>
    <GDP>165,800,000,000</GDP>
    <POPULATION>4,900,000</POPULATION>
 </UNIT>
 <UNIT>
    <STATE>California</STATE>   
    <!-- Note: the GDP node for this unit is missing -->
    <POPULATION>39,600,000</POPULATION>
 </UNIT>
 <UNIT>
    <STATE>Texas</STATE>
    <GDP>1,600,000,000,000</GDP>
    <POPULATION>28,300,000</POPULATION>
 </UNIT>
 <UNIT>
    <STATE>Michigan</STATE>
    <GDP>382,000,000</GDP>
    <POPULATION>10,000,000</POPULATION>
 </UNIT>
</STATE_DATA>

推荐答案

如果您求助于现代浏览器附带的 xml 处理功能,事情会得到一些简化.重写以 XPath 表达式为中心.完整的介绍超出了这个答案的范围,但简而言之,它是一种从 xml 树中检索内容的模式语言.

Things are simplified somewhat if you resort to the xml handling functionality that comes with modern browsers. The rewrite centers around XPath expressions. A complete intro is beyond the scope of this answer, but in a nutshell it's a pattern language to retrieve content from an xml tree.

xpath 表达式用于从 xml 文件中提取相关元素.

The xpath expressions are used to extract the relevant elements from the xml file.

该解决方案不需要对 xml 进行任何事先修改(与此解决方案的先前修订相反).

The solution does not require any prior modifications to the xml ( contrary to the prior revision of this solution ).

代码示例是独立的 - 只需将其保存为本地 html 文件或从 http 服务器提供.为了使其工作,xml 数据存储在作为数据岛的脚本元素中.

The code sample is standalone - just save it as a local html file or serve it from a http server. To make it work, the xml data is stored in a script element serving as a data island.

将该设计改回使用 ajax 调用获取 xml 数据应该很简单..

Changing that design back to fetching the xml data with an ajax call should be straightforward..

将代码视为概念证明,展示了基于 xpath 的方法的结构.

Consider the code a proof of concept presenting the structure of an xpath-based approach.

<!DOCTYPE html>
<!--
    SO
    datalist / xml handling
    Q 51200490 (https://stackoverflow.com/questions/51200490/how-to-find-the-node-position-of-a-value-in-an-xml-tree/51201494)
    A 
-->
<html>
    <head>
        <title>SO sample</title>
        <script>
 // Setup of keypress event handler, default selection of xml data.
 function setupEH () {
    var n = document.getElementById("myInputId");
    n.addEventListener("keyup", function(event) {
        event.preventDefault();
        if (event.keyCode === 13) {
            document.getElementById("myButton").click();
        }
    });

    loadXMLDoc('Alabama'); // comment out this line if you want a vanilla UI after loading the html page.
}

// Load the xml document
function loadXMLDoc( statelabel ) {
    // The xml document is retrieved with the following steps:
    //      1. Obtain the (in-document) source as a DOM node.
    //      2. Extract textual content.
    //      3. Instantiate the xml parser (a browser built-in)
    //      4. Parse textual content into an xml document
    //
    //  When retrieving the xml document by means of ajax, these steps will be handled by the library for you - a parsed xml document will be available as a property or through calling a method.
    //
    let x_xmlisland = document.getElementById("template_xml");
    let s_xmlsource = x_xmlisland.textContent; 
    let parser = new DOMParser();
    let xmlDoc = parser.parseFromString(s_xmlsource, "application/xml");

    myFunction(xmlDoc, statelabel); // Actual work ...
}

// Processing the xml document 
function myFunction(xmlDoc, statelabel) {
    //    debugger; // uncomment to trace

    //
    //  Every bit of information is processed as follows:
    //      - Get the relevant xml subtree ( `UNIT` element of the selected state incl.descendants )
    //      - Extract the textual value.
    //      - Feed the textual value to the Html elements prsenting the result.
    //
    var xpr_current_unit  = xmlDoc.evaluate("/STATE_DATA/UNIT[./STATE[./text() = '"+statelabel+"']]",xmlDoc,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null);
    var node_current_unit = xpr_current_unit.iterateNext();

    //
    //  The subsequent calls to xmlDoc.evaluate set the current UNIT element as their context node ('starting point'/'temporary root' for the xpath expression).
    //  The context node is referenced by '.' (dot) 
    //
    var xpr_s   = xmlDoc.evaluate("./STATE/text()",node_current_unit,null,XPathResult.ORDERED_ANY_TYPE,null);
    var node_s  = xpr_s.iterateNext();
    var s       = node_s.textContent
    document.getElementById("state").innerHTML = s;

    var xpr_g   = xmlDoc.evaluate("./GDP/text()",node_current_unit,null,XPathResult.ORDERED_ANY_TYPE,null);
    var node_g  = xpr_g.iterateNext();
    var g = "Unknown";
    if ( node_g !== null ) {
        g = node_g.textContent;
    }
    document.getElementById("gdp").innerHTML = g;

    var xpr_p   = xmlDoc.evaluate("./POPULATION/text()",node_current_unit,null,XPathResult.ORDERED_ANY_TYPE,null);
    var node_p  = xpr_p.iterateNext();
    var p = "Unknown";
    if ( node_p !== null ) {
        p = node_p.textContent;
    }
    document.getElementById("population").innerHTML = p;

    // cf. https://stackoverflow.com/a/3437009
    var xpr_u  = xmlDoc.evaluate("count(./preceding::UNIT)+1.",node_current_unit,null,XPathResult.ORDERED_ANY_TYPE,null);
    var n_ucount = xpr_u.numberValue;

    document.getElementById("inputValue").innerHTML = s;
    document.getElementById("nodePosition").innerHTML = n_ucount;
}

// Setup the submit click handler
function ehClick ( ) {
    let node_choice     = document.getElementById('myInputId');
    loadXMLDoc(node_choice.value);
}
        </script>
        <style>
        </style>
    </head>
    <body onload="setupEH()">
        <script id="template_xml" type="text/xml"><?xml version="1.0" encoding="UTF-8"?>
<STATE_DATA>
 <UNIT>
    <STATE>Wisconsin</STATE>
    <GDP>232,300,000,000</GDP>
    <POPULATION>5,800,000</POPULATION>
 </UNIT>
 <UNIT>
    <STATE>Alabama</STATE>
    <GDP>165,800,000,000</GDP>
    <POPULATION>4,900,000</POPULATION>
 </UNIT>
 <UNIT>
    <STATE>California</STATE>   
    <!-- Note: the GDP node for this unit is missing -->
    <POPULATION>39,600,000</POPULATION>
 </UNIT>
 <UNIT>
    <STATE>Texas</STATE>
    <GDP>1,600,000,000,000</GDP>
    <POPULATION>28,300,000</POPULATION>
 </UNIT>
 <UNIT>
    <STATE>Michigan</STATE>
    <GDP>382,000,000</GDP>
    <POPULATION>10,000,000</POPULATION>
 </UNIT>
</STATE_DATA>
        </script>
        <input list="myInput" id="myInputId" value="">
        <button id="myButton" onClick="ehClick()">submit</button>

        <p>input value: <span id="inputValue"></span></p>
        <p>XML tree node position of input value: <span id="nodePosition"></span></p>
        <p>State: <span id="state"></span></p>
        <p>GDP: <span id="gdp"></span></p>
        <p>Population: <span id="population"></span></p>

        <datalist id="myInput">
        <option id="AL">Alabama</option>
        <option id="CA">California</option>
        <option id="MI">Michigan</option>
        <option id="TX">Texas</option>
        <option id="WI">Wisconsin</option>
        </datalist>
    </body>
</html>

参考资料

  • XPath Programming (Document.evaluate) on MDN
  • Getting alternative values from html datalists
  • Determining xml element position with XPath

这篇关于如何在 XML 树中找到值的节点位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆