Заставить узлы игнорировать пространства имен (префиксы) после изменения структуры XML.PHP DOMDocument - PullRequest
0 голосов
/ 19 июня 2010

Оригинальный XML (myfile.xml)

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<blabla
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:cc="http://creativecommons.org/ns#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:blabla="http://www.w3.org/2000/blabla"
    xmlns="http://www.w3.org/2000/blabla"
    version="1.0">
    <title>Hello there</title>
    <metadata>
        <rdf:RDF>
            <cc:whtaat />
        </rdf:RDF>
    </metadata>
    <sometag>
        <anothertag id="anothertag1111">
            <andanother id="yep" />
        </anothertag >
    </sometag>
</blabla>

Целью является добавление дочернего элемента прямо под корневым узлом документа и «проталкивание» «исходных» дочерних элементов под новым дочерним элементом:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<blabla
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:cc="http://creativecommons.org/ns#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:blabla="http://www.w3.org/2000/blabla"
    xmlns="http://www.w3.org/2000/blabla"
    version="1.0">
    <magic>
        <title>Hello there</title>
        <metadata>
            <rdf:RDF>
                <cc:whtaat />
            </rdf:RDF>
        </metadata>
        <sometag>
            <anothertag id="anothertag1111">
                <andanother id="yep" />
            </anothertag >
        </sometag>
    </magic>
</blabla>

Этот php-скрипт делает это

<?php 
header("Content-type: text/xml");
// Create dom document
$doc = new DOMDocument(); 
$doc->load("myfile.xml");
$doc->preserveWhiteSpace = false; 
$doc->formatOutput = true; 
// Get first child (blabla)
$blablaNode = $doc->firstChild;
// Crete magic element to hold all children in blabla 
$magicElement = $doc->createElement('magic');
while($blablaNode->hasChildNodes()) {
    // Remove child from blablaNode and append it into magicElement
    $magicElement->appendChild($blablaNode->removeChild($blablaNode->firstChild));
}
// Append magicElement to blablaNode
$magicElement = $blablaNode->appendChild($magicElement);
echo $doc->saveXML();
?>

однако вывод

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<blabla xmlns:dc="http://purl.org/dc/elements/1.1/"
        xmlns:cc="http://creativecommons.org/ns#"
        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
        xmlns:blabla="http://www.w3.org/2000/blabla"
        xmlns="http://www.w3.org/2000/blabla" version="1.0">
<magic>
    <blabla:title xmlns:default="http://www.w3.org/2000/blabla">Hello there</blabla:title>
    <blabla:metadata xmlns:default="http://www.w3.org/2000/blabla" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#">
        <rdf:RDF>
            <cc:whtaat/>
        </rdf:RDF>
    </blabla:metadata>
    <blabla:sometag xmlns:default="http://www.w3.org/2000/blabla">
        <blabla:anothertag id="anothertag1111">
            <blabla:andanother id="yep"/>
        </blabla:anothertag>
    </blabla:sometag>
</magic>
</blabla>

Таким образом, к каждому узлу (который находится в пространстве имен «по умолчанию») прикреплен префикс «blaba»

<blabla:title />

Как этого избежать? При проверке текущих действий при изменении PHP на

while($blablaNode->hasChildNodes()) {
$removedChild = $blablaNode->removeChild($blablaNode->firstChild);
echo "(prefix for removed:".$removedChild->prefix.")";
$magicElement->appendChild($removedChild);
echo "(prefix for added:".$magicElement->lastChild->prefix.")";
}

echo is ... (префикс для удаленного:) (префикс для добавленного:) (префикс для удаленного:) (префикс для добавленного: по умолчанию ) ...

Заранее большое спасибо!

P.S. Это продолжение этого вопроса, поэтому «Или, может быть, у кого-то есть гораздо лучшее решение для достижения желаемого результата [добавление магического узла и толкание всего в нем]» по-прежнему применимо ...


Действительно, если «сначала объявить объявление пространства имен по умолчанию», как отмечает Джош Дэвис, префикс поиска пропадает. +1. Но это все как на выходе ...

...  
<metadata xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"  
xmlns:cc="http://creativecommons.org/ns#">
...  

... декларации все еще там. Уточнение. Я не создатель этих документов XML. Поэтому проверка позиции объявления пространства имен по умолчанию ... даже если она будет реализована, она не даст желаемого результата. И даже если эти декларации, добавленные libxml, должны быть там по стандарту, моя задача не проверять соответствие, а
- просто поместите все оригинальные дочерние узлы, без изменений в их содержимом (объявления, значения имен, атрибуты и т. д.) , в этот дополнительный вновь созданный контейнер.

1 Ответ

2 голосов
/ 19 июня 2010

Когда вы добавляете этих потомков, я полагаю, что libxml ищет первое объявление пространства имен для "http://www.w3.org/2000/blabla"" и находит "blabla". Теперь, если вы сначала поместите объявление пространства имен по умолчанию, он найдет пространство имен по умолчанию. работает, и это не будет префикс этих узлов с Blabla.

<blabla xmlns="http://www.w3.org/2000/blabla"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:cc="http://creativecommons.org/ns#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:blabla="http://www.w3.org/2000/blabla"
    version="1.0">

Обновление

Проблема полностью косметическая, но если вы хотите удалить избыточные объявления пространства имен, вы можете сбросить и перезагрузить XML:

$xml = $doc->saveXML();
$doc = new DOMDocument;
$doc->loadXML($xml, LIBXML_NSCLEAN);
echo $doc->saveXML();

Внимание, если вы повторно используете переменную $doc, это не значит, что такие вещи, как $blablaNode, останутся работоспособными, но не будут. Новый $doc - это новый документ.

О, и это также очистит избыточные пространства имен от исходного документа, возможно, нарушив это правило "держать его в целости".

О, и я забыл упомянуть, что вы должны явно указать, какое пространство имен <magic/> должно быть создано в:

$magicElement = $doc->createElementNS('http://www.w3.org/2000/blabla', 'magic');
...