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

У меня есть сценарий js, который читает и анализирует XML. Он получает XML из запроса XMLHttpRequest (который связывается со скриптом php, который возвращает XML). Сценарий должен получить 2 или более узлов под первым parentNode. Два необходимых узла имеют четко определенное имя, остальные могут быть любыми. Вывод из 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, ...), если это возможно и более эффективно.

2 ответа

Решение

Довольно просто пройтись по 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 (пробел) Класс RegExp. Обратите внимание, что некоторые реализации имеют проблемы с \s не достаточно инклюзивно (несколько "пустых" символов Unicode вне диапазона ASCII не совпадают и т. д.), поэтому обязательно проверьте свои данные.

Я бы просто попытался заменить очень грубую строку: предполагая, что вы храните ее в переменной с именем 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>
Другие вопросы по тегам