Последовательное получение текста из узлов XML

Я знаю, что об этом много спрашивали, но я последовал совету и все еще получаю очень конкретное, на первый взгляд непоследовательное поведение моих файлов xml / jQuery: Прежде чем я перейду к вопросу, вот мой jQuery:

$(document).ready(function() {
    var $body = $('body');
    var currentXMLObjects;
    var $currentXMLContainers = new Array();
    var previousXMLObjects;
    $body.append("<div id='content'><h3>Staff Organisational Chart</h1></div>");
    // Load the xml file using ajax 
    $.ajax({
        type: "GET",
        url: "xml/content.xml",
        dataType: "xml",
        success: function (xml) {
            $xml = $(xml);
            console.log(xml.children[0]);
            appendNewContainers(xml.children[0].children);
        }
    });

    function appendNewContainers(children) {
        currentXMLObjects = children;
        console.log("currentXMLObjects.length = "+currentXMLObjects.length);
        for (var x=0;x<currentXMLObjects.length;x++) {
            $currentXMLContainers.push( $( currentXMLObjects[x] ) );
            $("#content").append('<div class="container"><div>' + currentXMLObjects[x].childNodes[1].firstChild.nodeValue + '</div><div>' + currentXMLObjects[x].childNodes[1].firstChild.nodeValue + '</div><div>' + currentXMLObjects[x].childNodes[1].firstChild.nodeValue + '</div></div>');
        }
    }
});

А вот XML:

<content>
    <level name="first name">
        <title>Title 1 Here</title>
        <firstName>First Name 1</firstName>
        <lastName>Last Name 1</lastName>
        <contact>Active</contact> 
    </level>
    <level name="second name">
        <title>Title 2 Here</title>
        <firstName>First Name 2</firstName>
        <lastName>Last Name 2</lastName>
        <contact>Active</contact>
    </level>
    <level name="third name">
        <title>Title 3 Here</title>
        <firstName>First Name 3</firstName>
        <lastName>Last Name 3</lastName>
        <contact>Active</contact>
    </level>
    <level name="fourth name">
        <title>Title 4 Here</title>
        <firstName>First Name 4</firstName>
        <lastName>Last Name 4</lastName>
        <contact>Active</contact>
    </level>
    <level name="fifth name">
        <title>Title 5 Here</title>
        <firstName>First Name 5</firstName>
        <lastName>Last Name 5</lastName>
        <contact>Active</contact>
    </level>
</content>

Теперь я ПЫТАЮСЬ получить текст из узлов title, firstName и lastName и добавить их в div к содержащему его div.

Мне потребовалось некоторое время, экспериментируя с различными вариантами расположения .childNodes [0], firstChild и nodeValue, чтобы понять, что я могу получить текст каждого «заголовка», используя индекс «1» в currentXMLObjects [x] .childNodes [1 ] ... Проблема в том, что я не могу получить доступ к узлам firstName и lastName. Я перепробовал все возможные аранжировки:

currentXMLObjects [x] .childNodes [1] .childNodes [1] .nodeValue выдает нулевую ошибку, как и: currentXMLObjects [x] .childNodes [0] .childNodes [1] .nodeValue

currentXMLObjects [x] .childNodes [1] .nodeValue возвращает и добавляет «ноль», и

currentXMLObjects [x] .childNodes [2] .nodeValue ничего не добавляет.

Точно так же любая комбинация, в которой отсутствует средний «childNodes [n]», возвращает либо null, либо вообще ничего.

Кто-нибудь знает, что здесь происходит? Я удивлен, что узел «title» так глубоко вложен в XML; nodeList, отправляемый в функцию appendNewContainers, уже детализируется. Но поиск дочерних узлов элемента «level» не работает на меньшей глубине.

Любая помощь, очень признательна. Ваше здоровье.


person moosefetcher    schedule 28.01.2016    source источник


Ответы (2)


Почему бы вам не использовать jQuery также для данных xml? Посмотрите этот пример (используя вашу текущую структуру xml): jsFiddle

var $target = $('content');
$target.children().each(function(){
    $body.append($(this).attr('name') + "<br />");
    $body.append($('title', this).text() + "<br />");
    $body.append($('lastName', this).text() + "<br />");
    $body.append($('contact', this).text() + "<br />");
    $body.append('<br /><br/>');
});

Изменить:

Использование структуры вашего кода (включая пример с jQuery): jsFiddle

var xml = $('content');

appendNewContainers(xml[0].children);

function appendNewContainers(children) {
    currentXMLObjects = children;

    for (var x= 0; x < currentXMLObjects.length; x++) {
        $("#content").append(
            '<div class="container"><div>' + currentXMLObjects[x].children[0].innerText + 
            '</div><div>' + currentXMLObjects[x].children[1].innerText + 
            '</div><div>' + currentXMLObjects[x].children[2].innerText + '</div></div>'
        );
    }

    $('#content').append('<br style="margin-bottom: 40px" />');

    // jQuery way using tag names
    $(currentXMLObjects).each(function(){
        $("#content").append(
            '<div class="container"><div>' + $('title', this).text() + 
            '</div><div>' + $('firstName', this).text() + 
            '</div><div>' + $('lastName', this).text() + '</div></div>'
        );
    });
}
person kosmos    schedule 28.01.2016
comment
Спасибо за ответ - наверное, мне следовало сказать; Я использую внешний XML-файл, чтобы администратор (или кто-то с меньшим опытом программирования) мог обновить веб-приложение. Я действительно хотел бы знать, что происходит с той простой настройкой, которая у меня есть. - person moosefetcher; 28.01.2016
comment
После загрузки внешний файл становится XML-структурой, как в опубликованном мною примере. Я думаю, вы все усложняете. Ваш текущий код не работает, потому что вы пытаетесь получить доступ к несуществующим узлам. Я обновил свой ответ, указав ваш код. - person kosmos; 28.01.2016
comment
Еще раз спасибо за разъяснения. Хотя я не могу заставить эту работу работать с внешним файлом xml. Я также не понимаю, почему я могу получить доступ к узлам «title», а НЕ другим. Почему этих узлов не существует? - person moosefetcher; 29.01.2016
comment
Создайте console.log (или лучше используйте точку останова) и самостоятельно проверьте существующие свойства объектов. Я много работал со структурами xml для заполнения html и карт, и самый простой способ (с использованием jQuery) - использовать имена тегов. Проверьте и попробуйте использовать код внутри этого jsfiddle: jsfiddle.net/kmsdev/o1my8bm0. Думаю, это самый простой способ. - person kosmos; 29.01.2016
comment
Я чертовски разбирался с console.log, но это не прояснило ситуацию. Когда я получаю возвращенный текстовый объект, я не могу извлечь никакой текст. Некоторые объекты будут иметь длину, но я не могу получить к ним доступ с помощью квадратных скобок. Также проблема с использованием имен тегов заключается в том, что я хочу получать теги только определенной глубины - когда пользователь перемещается вверх и вниз по иерархии персонала. Думаю, я собираюсь переключиться на один тип тега ('level') и использовать атрибуты (например, name = name здесь) для описания каждого элемента. - person moosefetcher; 29.01.2016

Можно ли добавить полученный xml к документу и запросить содержимое с помощью querySelectors? Что-то вроде (простой пример без jQuery, но должен быть простой в использовании jQuery для добавления xml и его запроса):

var xml = document.querySelector('content');

var names = document.querySelectorAll('[name]');
var result = document.querySelector('#result');

[].slice.call(names).forEach(
  function(nameElement) {
    result.textContent += 
      nameElement.querySelector('firstName').textContent + ' ' +
      nameElement.querySelector('lastName').textContent +
      '\n';
  } 
);
content {
  display: none;
 }
<pre id="result"></pre>

<content>
    <level name="first name">
        <title>Title 1 Here</title>
        <firstName>First Name 1</firstName>
        <lastName>Last Name 1</lastName>
        <contact>Active</contact> 
    </level>
    <level name="second name">
        <title>Title 2 Here</title>
        <firstName>First Name 2</firstName>
        <lastName>Last Name 2</lastName>
        <contact>Active</contact>
    </level>
    <level name="third name">
        <title>Title 3 Here</title>
        <firstName>First Name 3</firstName>
        <lastName>Last Name 3</lastName>
        <contact>Active</contact>
    </level>
    <level name="fourth name">
        <title>Title 4 Here</title>
        <firstName>First Name 4</firstName>
        <lastName>Last Name 4</lastName>
        <contact>Active</contact>
    </level>
    <level name="fifth name">
        <title>Title 5 Here</title>
        <firstName>First Name 5</firstName>
        <lastName>Last Name 5</lastName>
        <contact>Active</contact>
    </level>
</content>

person KooiInc    schedule 28.01.2016
comment
У меня будут элементы «уровня», вложенные в элементы «уровня», поэтому я не думаю, что этот подход сработает; Я пытаюсь передать только «текущую» глубину элементов «уровня» функции appendNewContainers (конечное веб-приложение будет представлять иерархию персонала). Поэтому я не могу собирать элементы по атрибуту «имя», поскольку элементы «уровня» на любой глубине будут иметь этот атрибут. - person moosefetcher; 28.01.2016
comment
Если у вас есть контроль над XML, должна быть возможность добавлять к нему уникальные атрибуты (данные) для идентификации конкретных (диапазонов) элементов. Возможно, использование json также является жизнеспособной альтернативой. - person KooiInc; 28.01.2016
comment
XML должен быть как можно более простым, чтобы администраторы могли поддерживать веб-приложение (не в обиду администраторам). Есть идеи, почему я могу получить доступ к узлу «title», но не к узлам «firstName» или «lastName»? - person moosefetcher; 28.01.2016