使用递归解析高度嵌套的 XML 以获取所有 sys_id 直到 'TestBS4' 为每个 child of `<childrenOfCurrentCI>`

Parse a highly nested XML to fetch all the sys_id's till 'TestBS4' for each child of `<childrenOfCurrentCI>` using recursion

工具:ServiceNow。语言:JavaScript

我的方法:我在每个级别使用 while 循环进行迭代以达到'TestBS4'的sys_id,我必须在其中放置 4 个 while 循环另一个一旦我在 <childrenOfCurrentCI> 标签内有了第一个 <CI>...</CI> 节点。我觉得这可以通过递归来完成,但我做不到。

如果我有 50 个 CI child 一个在另一个里面(不是兄弟姐妹),我需要第 45 个怎么办?我很感激有人使用递归来帮助实现这一目标。 sys_id 可以放在数组中以供进一步处理。

在这种情况下,我需要 <childrenOfCurrentCI> 的每个 child 的所有 sys_id 直到第 4 级(TestBS4) 标签。


下面是示例 XML。

<?xml version="1.0" encoding="UTF-8"?>
<xmlTree>
   <sys_id>e9c23f4adbf31300ae2af28239961974</sys_id>
   <name>Test CI One</name>
   <relType>SELF</relType>
   <childrenOfCurrentCI>
      <CI>
         <sys_id>68b1b746dbf31300ae2af2823996197a</sys_id>
         <name>TestBS1</name>
         <relType>Depends on::Used by</relType>
         <children>
            <CI>
               <sys_id>964477cedbf31300ae2af28239961913</sys_id>
               <name>TestBS2</name>
               <relType>Depends on::Used by</relType>
               <children>
                  <CI>
                     <sys_id>88643fcedbf31300ae2af2823996190b</sys_id>
                     <name>TestBS3</name>
                     <relType>Depends on::Used by</relType>
                     <children>
                        <CI>
                           <sys_id>0264f7cedbf31300ae2af28239961971</sys_id>
                           <name>TestBS4</name>
                           <relType>Depends on::Used by</relType>
                           <children>
                              <CI>
                                 <sys_id>fb64ffcedbf31300ae2af282399619e8</sys_id>
                                 <name>TestBS5</name>
                                 <relType>Depends on::Used by</relType>
                              </CI>
                           </children>
                        </CI>
                     </children>
                  </CI>
               </children>
            </CI>
         </children>
      </CI>
      <CI>
         <sys_id>ae1ff02fdbfb1300ae2af2823996195d</sys_id>
         <name>Test Side Parent One</name>
         <relType>Depends on::Used by</relType>
      </CI>
   </childrenOfCurrentCI>
</xmlTree>

刚刚为案例编码

In this case, I need all the sys_id's till the 4th level (TestBS4) of each child of tag.

希望你明白了。

var text = `
<xmlTree>
   <sys_id>e9c23f4adbf31300ae2af28239961974</sys_id>
   <name>Test CI One</name>
   <relType>SELF</relType>
   <childrenOfCurrentCI>
      <CI>
         <sys_id>68b1b746dbf31300ae2af2823996197a</sys_id>
         <name>TestBS1</name>
         <relType>Depends on::Used by</relType>
         <children>
            <CI>
               <sys_id>964477cedbf31300ae2af28239961913</sys_id>
               <name>TestBS2</name>
               <relType>Depends on::Used by</relType>
               <children>
                  <CI>
                     <sys_id>88643fcedbf31300ae2af2823996190b</sys_id>
                     <name>TestBS3</name>
                     <relType>Depends on::Used by</relType>
                     <children>
                        <CI>
                           <sys_id>0264f7cedbf31300ae2af28239961971</sys_id>
                           <name>TestBS4</name>
                           <relType>Depends on::Used by</relType>
                           <children>
                              <CI>
                                 <sys_id>fb64ffcedbf31300ae2af282399619e8</sys_id>
                                 <name>TestBS5</name>
                                 <relType>Depends on::Used by</relType>
                              </CI>
                           </children>
                        </CI>
                     </children>
                  </CI>
               </children>
            </CI>
         </children>
      </CI>
      <CI>
         <sys_id>ae1ff02fdbfb1300ae2af2823996195d</sys_id>
         <name>Test Side Parent One</name>
         <relType>Depends on::Used by</relType>
      </CI>
   </childrenOfCurrentCI>
</xmlTree>

`;

if (window.DOMParser)
{
    parser = new DOMParser();
    xmlDoc = parser.parseFromString(text, "text/xml");
}
else // Internet Explorer 
{
    xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
    xmlDoc.async = false;
    xmlDoc.loadXML(text);
}
let sysIds = xmlDoc.getElementsByTagName("childrenOfCurrentCI")[0].getElementsByTagName("sys_id");
function getMeSysId(position) {
  console.log(sysIds[position-1].textContent);
}
console.log("to get the 4th level sys_Id");
getMeSysId(4);
console.log("for all the sysid's inside childrenOfCurrentCI");
for (let i=0; i<sysIds.length;i++) {
  console.log(sysIds[i].textContent);
}

使用 var 而不是 let else 条件可以跳过(IE 版本需要) 并尝试使用 serviceNow xml dom parser

所以更新后的代码块是

    xmlDoc = new XMLDocument(text);

var sysIds = xmlDoc.getElementsByTagName("childrenOfCurrentCI")[0].getElementsByTagName("sys_id");

如果您希望通过 XML 的名称检索 CI 的 sys_id,我建议使用 XPath,它是 XML 操作的辅助工具。 ServiceNow XMLDocument2 对象将帮助您解析您的 XML。这是您案例的示例代码

var xmlString = 'YOUR_XML';
var ciName = 'TestBS4';
var xPath = "//CI/name[text() = '" + ciName + "']/../sys_id/text()";

var xmlDoc = new XMLDocument2();
xmlDoc.parseXML(xmlString);

var sysID = xmlDoc.getNode(xPath).toString();
gs.log(sysID);

getNode 方法中使用的 XPath 在 XML 中查找具有 ciName 变量值的 CI/name 节点。然后向上一个节点检索 sys_id 节点的值。