Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml 如何在片段创建中使用全局命名空间定义?_Xml_Domdocument_Libxml2 - Fatal编程技术网

Xml 如何在片段创建中使用全局命名空间定义?

Xml 如何在片段创建中使用全局命名空间定义?,xml,domdocument,libxml2,Xml,Domdocument,Libxml2,根元素具有类似xmlns:xlink=”的命名空间声明http://www.w3.org/1999/xlink“。。。因此,任何附加的节点(例如通过appendChild)都将接受名称空间。我可以附加,因为总的来说它是有效的。。。但是要附加一个片段,我首先需要使用createDocumentFragment()创建片段 例如: $tmp=$dom->createDocumentFragment(); $ok=$tmp->appendXML(“”); 运行时,会生成一个错误, DOMDocum

根元素具有类似
xmlns:xlink=”的命名空间声明http://www.w3.org/1999/xlink“
。。。因此,任何附加的节点(例如通过
appendChild
)都将接受名称空间。我可以附加
,因为总的来说它是有效的。。。但是要附加一个片段,我首先需要使用
createDocumentFragment()
创建片段

例如:

$tmp=$dom->createDocumentFragment();
$ok=$tmp->appendXML(“”);
运行时,会生成一个错误,

DOMDocumentFragment::appendXML():命名空间错误:
未定义内联图形上href的命名空间前缀xlink

如何对
DOMDocumentFragment::appendXML()
方法说“使用DomDocument名称空间”


注释和上下文
(,不要在这里争论)

它看起来像是按照它应该的方式工作。退房chregu@php.net说这不是一个bug,而且工作正常。虽然我同意bug报告和其他评论,但是由于片段是由DOMDocument组成的,并且它定义了名称空间,所以它实际上应该知道它们是什么,并且应该可以正常工作

将名称空间与元素一起传入。它不会显示在输出的XML中,但会被片段读取,这样它就可以创建属性而不会出现任何错误

$dom = new DOMDocument('1.0', 'utf-8');
$root = $dom->createElement('MyRoot');
$root->setAttributeNS('http://www.w3.org/2000/xmlns/','xmlns:xlink','http://www.w3.org/1999/xlink');
$dom->appendChild($root);

$tmp = $dom->createDocumentFragment();
$ok = $tmp->appendXML('<graphic xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="file123.ext"/>');
$dom->documentElement->appendChild($tmp);
die($dom->saveXML());
$dom=新的DOMDocument('1.0','utf-8');
$root=$dom->createElement('MyRoot');
$root->setAttributeNS('http://www.w3.org/2000/xmlns/“,”xmlns:xlink“,”http://www.w3.org/1999/xlink');
$dom->appendChild($root);
$tmp=$dom->createDocumentFragment();
$ok=$tmp->appendXML(“”);
$dom->documentElement->appendChild($tmp);
die($dom->saveXML());
输出

<?xml version="1.0" encoding="utf-8"?>
<MyRoot xmlns:xlink="http://www.w3.org/1999/xlink"><graphic xlink:href="file123.ext"/></MyRoot>

这不是一个bug,它确实是预期的行为。名称空间不是在XML文档上或为XML文档定义的,而是在元素节点上定义的。在重新定义之前,它们对该节点和所有子节点都有效

因此,如果您创建文档片段,它没有父节点,现在您添加了一些XML片段。查找它时,找不到名称空间的任何定义,您会得到一个错误。根据要在文档中添加名称空间的位置,名称空间前缀可用于完全不同的名称空间

您必须在片段中定义名称空间,如果片段是由DOM生成的,那么它应该始终具有所有需要的名称空间定义

$dom = new DOMDocument();
$dom->loadXml('<foo/>');

$fragment = $dom->createDocumentFragment();
$fragment->appendXML(
  '<fragment xmlns:xlink="http://www.w3.org/1999/xlink">
     <graphic xlink:href="file123.ext"/>
   </fragment>'
);
foreach ($fragment->firstChild->childNodes as $child) {
  $dom->documentElement->appendChild($child->cloneNode(TRUE));
}

echo $dom->saveXML();
如果将其生成为文本,则可以确保命名空间定义包含在需要它的元素中,或者可以添加包含所有所需命名空间定义的包装器元素节点

$dom = new DOMDocument();
$dom->loadXml('<foo/>');

$fragment = $dom->createDocumentFragment();
$fragment->appendXML(
  '<fragment xmlns:xlink="http://www.w3.org/1999/xlink">
     <graphic xlink:href="file123.ext"/>
   </fragment>'
);
foreach ($fragment->firstChild->childNodes as $child) {
  $dom->documentElement->appendChild($child->cloneNode(TRUE));
}

echo $dom->saveXML();
输出:

<?xml version="1.0"?>
<foo>
  <graphic xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="file123.ext"/>
</foo>
<fragment xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:xlink="http://www.w3.org/1999/xlink"><graphic xlink:href="file123.ext"/></fragment>

关于这个问题以及与PHP的关系的注释缺少片段名称空间的资源

一个PHP错误? (在@slapyo之后)

有一个:不是一个“好行为”;是一个bug(!)。如果您同意,请在此处添加评论,并在此处投票(!)


假设您使用
replace\u innerXML($node,$innerXML)
函数或任何其他类似上下文。。。请参阅下面的“典型场景”部分

如何解决? 如果没有一个大的正则表达式(在本例中超过
$innerXML
)和缓慢的算法,那么在没有名称空间声明的情况下设置每个标记。。。当然,毕竟,
appendXML()
将片段变成了树的一个组件,因此不需要名称空间,因为它已经在根目录中了。。。所有的工作只是使用bug片段的
appendXML()

典型情景 (在@ThW回答/讨论之后)典型的“盲名称空间”片段使用

当片段是具有新名称空间的“Exterterterrenal”时,好的,片段需要自己声明所使用的名称空间。。。但这个问题所暴露的问题并不是这个奇异的问题,而是另一个非常普遍的问题
PS:正如我们将要讨论的,“PHP bug”解决方案也是针对这种情况的解决方案

这里,为了举例说明,片段有两种典型的用法,其中不存在关于名称空间的先验知识(由片段的元素使用),只有在DOMDocument中声明了所有名称空间的事实(不需要重新声明)

1) a

2) 一个“通用DOM库”,它提供了一种处理方法,用新的XML内容(可以是片段内容)替换节点的XML内部内容。请参见下面的函数
replace\u innerXML()

function replace_innerXML(DOMNode$e,$innerXML=''){
if($e&($innerXML>“”| |$e->nodeValue>“”)){
$e->nodeValue='';
如果($innerXML>“”){
$tmp=$e->ownerDocument->createDocumentFragment();
//这里我们需要将名称空间声明注入$innerXML
$tmp->appendXML($innerXML);
$e->appendChild($tmp);
}
返回true;
}
返回false;
}
//此功能仅用于说明其他道具
//看https://stackoverflow.com/q/26029868/287948
//使用示例:
$innerXML='nonoo-uuu-nono,PHP有一个bug,因为它不提供任何(!)

象形解 “注入名称空间”的唯一方法(今天是2014年)是

  • 步骤#1:,获取“名称空间1”、“名称空间2”等
  • 步骤2:通过()检测所有名称空间,使用类似于
$innerXML=preg\u replace\u回调(
“/([]+)/s”,
函数($m)使用($namespacesAssociative){
$nsdecl=“xmlns:$m[2]=\”“.$namespacesAssociative[$m[2]]”;

return($m[1]='我为此花了大约4个小时的时间,如果关闭libxml错误,警告就会消失,您可以自由使用前缀,而无需麻烦

libxml_use_internal_errors(true);
我同意这更多的是一个bug而不是设计上的bug,但是这个解决方法为我节省了时间

编辑:如果您不需要返回并在以后的脚本中引用该片段,则可以使用该选项。似乎取消该警告仍会保留项目