我熟悉 DOMDocument :: importNode 方法,用于从其他文档元素导入节点树。
然而,我想知道的是,如果我在导入它们时可以自动更改节点树上的命名空间前缀,即为该命名空间的所有节点指定一个新前缀。
假设现有文档中的节点都具有“name”,“identity”等名称。将它们导入我的新文档时,它们将与其他命名空间一起使用,因此我希望它们显示为“nicnames:name”,“nicnames:identity”等等。我希望能够以编程方式更改此前缀,以便在另一个上下文中我可以将它们导入,例如,“myprefix:name”,“myprefix:identity”,具体取决于它们导入的文档。
编辑:根据我的回答中的解释,我发现我实际上并不需要这样做。我误解了XML中的命名空间。
答案 0 :(得分:0)
您可能必须编写自己的导入代码。 E.g。
function importNS(DOMNode $target, DOMNode $source, $fnImportElement, $fnImportAttribute) {
switch($source->nodeType) {
case XML_ELEMENT_NODE:
// invoke the callback that creates the new DOMElement node
$newNode = $fnImportElement($target->ownerDocument, $source);
if ( !is_null($newNode) && !is_null($source->attributes) ) {
foreach( $source->attributes as $attr) {
importNS($newNode, $attr, $fnImportElement, $fnImportAttribute);
}
}
break;
case XML_ATTRIBUTE_NODE:
// invoke the callback that creates the new DOMAttribute node
$newNode = $fnImportAttribute($target->ownerDocument, $source);
break;
default:
// flat copy
$newNode = $target->ownerDocument->importNode($source);
}
if ( !is_null($newNode) ) {
// import all child nodes
if ( !is_null($source->childNodes) ) {
foreach( $source->childNodes as $c) {
importNS($newNode, $c, $fnImportElement, $fnImportAttribute);
}
}
$target->appendChild($newNode);
}
}
$target = new DOMDocument;
$target->loadxml('<foo xmlns:myprefix="myprefixUri"></foo>');
$source = new DOMDocument;
$source->loadxml('<a>
<b x="123">...</b>
</a>');
$fnImportElement = function(DOMDocument $newOwnerDoc, DOMElement $e) {
return $newOwnerDoc->createElement('myprefix:'.$e->localName);
};
$fnImportAttribute = function(DOMDocument $newOwnerDoc, DOMAttr $a) {
// could use namespace here, too....
return $newOwnerDoc->createAttribute($a->name);
};
importNS($target->documentElement, $source->documentElement, $fnImportElement, $fnImportAttribute);
echo $target->savexml();
打印
<?xml version="1.0"?>
<foo xmlns:myprefix="myprefixUri"><myprefix:a>
<myprefix:b x="123">...</myprefix:b>
</myprefix:a></foo>
答案 1 :(得分:0)
我发现我误解了XML命名空间。它们实际上比我想象的要好得多。
我认为单个文档中使用的每个XML命名空间必须具有不同的命名空间前缀。事实并非如此。
即使没有名称空间前缀,您也可以在整个文档中使用不同的名称空间,只需在适当的位置包含xmlns属性,并且xmlns属性仅对该元素及其后代有效,覆盖可能已设置的该前缀的名称空间在树上更高。
例如,要在另一个名称空间中拥有一个名称空间,您不必执行以下操作:
<record xmlns="namespace1">
<person:surname xmlns:person="namespace2">Smith</person:surname>
</record>
你可以做到
<record xmlns="namespace1">
<surname xmlns="namespace2">Smith</person>
</record>
命名空间前缀在某些情况下是一个很好的快捷方式,但在将一个文档包含在另一个不同命名空间中时则不一定。