0

元の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 ...(削除されたプレフィックス:)(追加されたプレフィックス:)(削除されたプレフィックス:)(追加されたプレフィックス:デフォルト)..

よろしくお願いします!

PSこれはこの質問の続編であるため、「または、誰かが望ましい結果を達成するための一般的にはるかに優れたソリューションを持っている可能性があります[マジックノードを追加し、その中にすべてをプッシュする]」はまだ適用されます...


実際、Josh Davisが指摘しているように、「デフォルトの名前空間宣言を最初に置く」場合、ルックアッププレフィックスはなくなります。+1。しかし、それは出力のようにそれです...

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

...宣言はまだあります。明確化。私はそれらのXMLドキュメントの作成者ではありません。したがって、デフォルトの名前空間宣言の位置を確認します...実装されていても、望ましい結果は得られません。そして、libxmlによって追加された宣言が標準で存在する必要がある場合でも、私のタスクは適合性を検証することではありませんが、
すべての元の子ノードをコンテンツ(宣言、名前、値、属性など)にそのまま入れて、新しく作成されたものの下に置くだけです。容器。

4

1 に答える 1

2

それらの子を追加すると、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が機能し続けるという意味ではなく、そうではないことに注意してください。new$docは新しいドキュメントです。

ああ、それはまた、元のドキュメントから冗長な名前空間をクリーンアップし、「そのままにしておく」というルールを破る可能性があります.

ああ、言い忘れていました<magic/>が、作成する名前空間を明示的に宣言する必要があります。

$magicElement = $doc->createElementNS('http://www.w3.org/2000/blabla', 'magic');
于 2010-06-19T01:28:34.420 に答える