Навигация по DOM: устранение текстовых узлов

#javascript #xmldom

#javascript #xmldom

Вопрос:

У меня есть js-скрипт, который считывает и анализирует XML. Он получает XML из запроса XMLHttpRequest (который связывается со скриптом php, который возвращает XML). Предполагается, что скрипт получит 2 или более узлов под первым родительским узлом. У двух узлов, которые для этого требуются, имя четко определено, у остальных может быть любое имя. Вывод из php может быть:

 <?xml version='1.0'?>
<things>
    <carpet>
        <id>1</id>
        <name>1</name>
        <desc>1.5</desc>
    </carpet>
    <carpet>
        <id>2</id>
        <name>2</name>
        <height>unknown</height>
    </carpet>
</things>
  

Здесь все ковры имеют 7 узлов.

но это также может быть:

 <?xml version='1.0'?>
<things>
    <carpet>
        <id>1</id>
        <name>1</name>
        <desc>1.5</desc>
    </carpet>
    <carpet><id>2</id><name>2</name><height>unknown</height></carpet>
</things>
  

Здесь первый ковер имеет 7 узлов, второй ковер имеет 3 узла.
Я хочу, чтобы мой код javascript обрабатывал оба точно так же быстрым и чистым способом.
Если возможно, я бы хотел удалить все текстовые узлы между каждым тегом. Таким образом, код, подобный приведенному выше, всегда будет обрабатываться как:

 <?xml version='1.0'?>
    <things><carpet><id>1</id><name>1</name><desc>1.5</desc></carpet><carpet><id>2</id><name>2</name><height>unknown</height></carpet></things>
  

Возможно ли это быстрым и эффективным способом? Я бы хотел не использовать какую-либо функцию get (getElementsByTagName(), getElementById, …), если это возможно и если это более эффективно.

Ответ №1:

Довольно просто обойти DOM и удалить узлы, которые вы считаете пустыми (содержащими только пробелы).

Это непроверенное (протестировано и исправлено, живая копия здесь), но это выглядело бы примерно так (замените эти магические числа символами, очевидно):

 var reBlank = /^s*$/;
function walk(node) {
    var child, next;
    switch (node.nodeType) {
        case 3: // Text node
            if (reBlank.test(node.nodeValue)) {
                node.parentNode.removeChild(node);
            }
            break;
        case 1: // Element node
        case 9: // Document node
            child = node.firstChild;
            while (child) {
                next = child.nextSibling;
                walk(child);
                child = next;
            }
            break;
    }
}
walk(xmlDoc); // Where xmlDoc is your XML document instance
  

Там мое определение «пустого» — это все, что имеет пробелы только в соответствии с пониманием интерпретатора JavaScript s (пробел) Класс регулярных выражений. Обратите внимание, что некоторые реализации имеют проблемы с s недостаточным включением (несколько «пустых» символов Unicode за пределами диапазона ASCII не совпадают и т.д.), Поэтому обязательно протестируйте с вашими образцами данных.

Комментарии:

1. Я не буду использовать ваше предложение, но вы дали мне идею, которая мне нужна, чтобы сделать шаг вперед, которого достаточно для решения этой проблемы, спасибо.

2. @brunoais: Хорошая сделка, рад, что помогло.

3. @brunoais Не хотите поделиться своим собственным решением / что вы в итоге сделали? Просто ради интереса.

Ответ №2:

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

 var rex = /(<(/)?[A-Za-z0-9] >)(s) /gi;
var a = xml.replace( rex, "$1" );
  

вот полный тест, который я собрал:

 <html><head></head>

<body>
<script type="text/javascript">
var xml = "<?xml version='1.0'?>n"   
"<things>n"  
"    <carpet>n"  
"        <id>1</id>n"  
"        <name>1</name>n"  
"        <desc>1.5</desc>n"  
"    </carpet>n"  
"    <carpet>n"  
"        <id>2</id>n"  
"        <name>2</name>n"  
"        <height>unknown</height>n"  
"    </carpet>n"  
"</things>";

var rex = /(<(/)?[A-Za-z0-9] >)(s) /gi;
var a = xml.replace( rex, "$1" );
alert( a );

</script>


</body></html>
  

Комментарии:

1. @Liv ваше решение использует регулярное выражение, которое является средним или медленным способом решения. Кроме того, вы предполагаете, что я получаю текст с сервера, что неверно, я получаю объект XML. Извините, но ваше решение не является решением.

2. ваш XMLHttpRequest позволяет вам извлекать ответ в виде текста через его свойство responseText . Кроме того, обработка регулярных выражений выполняется не медленно — это заблуждение; вы обнаружите, что на самом деле это намного быстрее, чем написание собственного кода для выполнения поиска и замены в строке; более того, это определенно быстрее, чем обход DOM! Но я принимаю тот факт, что вы не хотите использовать регулярные выражения и предпочитаете методы только DOM.

3. Использование регулярных выражений для изменения разметки XML или HTML в масштабе макроса, как правило, работает не очень хорошо.

4. @T.J. Crowder : Прошу, уточните!

5. Я слышал вас — regex не подходит для синтаксического анализа XML В целом. Однако, учитывая XML, описанный в приведенном выше вопросе, когда нет атрибутов и т.д., регулярное выражение будет работать. Другими словами, я ответил на ЭТОТ вопрос не на общий вопрос о разборе XML с использованием регулярных выражений. (И да, я согласен с вашей точкой зрения, что регулярное выражение — неправильный способ анализа XML!)