通过JavaScript中的标记名称遍历XML DOM的所有直接子项

时间:2015-01-21 22:30:53

标签: javascript xml dom

我有这种动态XML要解析,其中section标签总是有一个“allSubSections”标签,可能会或可能不会填充更多部分(完全相同的xml格式)。由于每个部分都有“allSubSections”标记,理论上它可以在嵌套部分非常深入,但在实际使用中,通常只有几个级别。我的XML文档中只有一个“allSections”标记。这是XML:

<poAssessMentVersion>
    <allSections>
        <section>
            <allSubSections>
                <section>
                    <allSubSections></allSubSections>
                </section>
                <section>
                    <allSubSections>
                         <section>
                             <allSubSections></allSubSections>
                         <section>
                    </allSubSections>
                </section>
            </allSubSections>
        <section>
    <allSections>
</poAssessmentVersion>

所以我需要循环,从这个xml中创建javascript对象。与XML一样,对象可以具有与其自身类似的子部分。我相信我只需要通过“allSections”的直接子项循环,标记名称为“section”作为第一步。我该怎么办?我刚问了一个问题Here, about doing that, but not cycling through a collection tag 并得到了一个很好的答案。现在我需要这个集合标签“allSections”的等效答案,这是我当前的代码:

var theSections = xml.querySelectorAll("poAssessmentVersion>allSections");

    for (i = 0; i < theSections.length; i++) {

        var section = new AssessmentSection();
        section.description = theSections[i].querySelectorAll("AssessmentSection>description")[theSections.length - i].childNodes[0].nodeValue;
        version.allSections.push(section);
    }

有没有办法在标签中循环只获得immeditate的孩子?我觉得我当前的代码越来越接近但是我的部分列表的顺序并不完全正确。在我的示例XML中,我将<AssessmentSection>写为<section>,但在我的xml中它实际上是<assessmentSection>

2 个答案:

答案 0 :(得分:0)

我改变了你的XML:

  • 修复未关闭的标签
  • <section>替换为<assessmentSection>(基于您的&#34;但我的xml中确实是<assessmentSection>&#34;
  • 在每个<title>中添加<assessmentSection>个节点作为示例
<poAssessMentVersion>
  <allSections>

    <!-- level #1 / section 1 -->
    <assessmentSection>
      <title>level #1: section 01</title>

      <allSubSections>

        <!-- level #2 / section 1 -->
        <assessmentSection>
          <title>level #2: section 01</title>
          <allSubSections></allSubSections>
        </assessmentSection>

        <!-- level #2 / section 2 -->
        <assessmentSection>
          <title>level #2: section 02</title>
          <allSubSections>

            <!-- level #3 / section 1 -->
            <assessmentSection>
              <title>level #3: section 01</title>
              <allSubSections></allSubSections>
            </assessmentSection>
            <!-- end of level #3 / section 1 -->

          </allSubSections>
        </assessmentSection>
        <!-- end of level #2 / section 2 -->

      </allSubSections>
    </assessmentSection>
    <!-- end of level #1 / section 1 -->

  </allSections>
</poAssessMentVersion>

JavaScript代码

// helper, convert to Array
function toArray(obj) {
  return Array.prototype.slice.call(obj);
}

// return value of the <title> node or empty string
function getSectionTitle(node) {
  try {
    return node.querySelector('title').childNodes[0].nodeValue;
  }
  catch(e) {
    return '';
  }
}

// counter for custom attribute name
var attributeCoutner = 0;

// generate unique attribute name
function getAttributeName() {
  return 'x-custom-attr-' + (attributeCoutner++);
}

// parse "root" <poAssessMentVersion> node
function parseRootNode(node) {
  var attrName = getAttributeName();

  node.setAttribute(attrName, true);
  var selector = '[' + attrName + '] > allSections > assessmentSection';
  var children = node.parentNode.querySelectorAll(selector) || [];
  node.removeAttribute(attrName);

  return toArray(children).map(parseSectionNode);
}

// parse <assessmentSection> node
function parseSectionNode(node) {
  var attrName = getAttributeName();

  node.setAttribute(attrName, true);
  var selector = '[' + attrName + '] > allSubSections > assessmentSection';
  var children = node.parentNode.querySelectorAll(selector) || [];
  node.removeAttribute(attrName);

  return {
    title: getSectionTitle(node),
    subSections: toArray(children).map(parseSectionNode)
  };
}

// start parsing
function parseXml(xml) {
  return parseRootNode(xml.documentElement);
}

// I suppose that you load XML with help AJAX
function onXml(err, xml) {
  if(err) {
    return console.log(err);
  }
  var sections = parseXml(xml);
  console.log(JSON.stringify(sections));
}

console.log的结果将如下所示

[
  {
    "title": "level #1: section 01",
    "subSections": [
      {
        "title": "level #2: section 01",
        "subSections": []
      }, 
      {
        "title": "level #2: section 02",
        "subSections": [
          {
            "title": "level #3: section 01",
            "subSections": []
          }
        ]
      }
    ]
  }
]

答案 1 :(得分:0)

我的回答可能不是最好的,但在我看到此处发布的另一个答案之前,这就是我所做的,并且它有效。我通过硬编码childnode索引得到<allSections>标记,然后循环遍历部分列表,从节点索引构建我的对象,如下所示:

function getTheSections(sectionXML) {
    var section = getSection(sectionXML);
    var theQuestions = sectionXML[0].childNodes;
    for (x = 0; x < theQuestions.length; x++) {
        questionXML = theQuestions[x].childNodes;
        var question = getQuestion(questionXML);
        var theItems = questionXML[0].childNodes;
        for (y = 0; y < theItems.length; y++) {
            itemXML = theItems[y];
            var item = getItem(itemXML);
            question.allItems.push(item);
        }
        section.allQuestions.push(question);
    }
    return section;
}

function getSection(SectionXML) {
    var section = new AssessmentSection();
    section.code = SectionXML[2].childNodes[0];
    section.description = SectionXML[3].childNodes[0];

    section.code = section.code ? section.code.nodeValue : "";
    section.description = section.description ? section.description.nodeValue : "";
    return section;
}