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>