如何在XML树中查找值的节点位置?

时间:2018-07-05 22:04:54

标签: javascript xmlhttprequest

基于我在页面上输入的值,我想要检索相关的XML数据。

例如,如果我从页面上的option输入字段中输入/选择datalist“ Michigan”,我想在{{1 }}文件。通过知道node的位置,我可以从XML文档中检索与密歇根州相对应的其他信息,例如nodeXML

我知道我应该将GDP更改为POPULATION之类的变量,但是该如何编码该函数?

[1]
[i]

这是我的XML:

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

1 个答案:

答案 0 :(得分:1)

如果您诉诸于现代浏览器附带的xml处理功能,事情将有所简化。 重写围绕XPath表达式进行。完整的介绍超出了此答案的范围,但简而言之,它是一种从xml树检索内容的模式语言。

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

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

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

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

将代码视为概念证明,介绍基于xpath的方法的结构。

<!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>

参考