我最近对XML命名空间感到非常悲痛,并在PHP中有效地处理它们。以下是最糟糕的罪魁祸首的样本:
<dc:type xsi:type="TypeName" xsi:identifier="NN">Others</dc:type>
我使用preg_replace成功设法做的是使用以下方法“取消命名”标记(不破坏URL):
$xml = preg_replace(
'/<(\/?)([^:" ].*):([^>\/ ].*)(\/?)>/msiU',
'<$1$2_$3$4>',
$x->readOuterXML()
);
# <dc_type xsi:type="TypeName" xsi:identifier="NN">Others</dc_type>
我不能做 - 通过缺乏正则表达式魔法 - 将所有命名空间属性转换为相同的格式。我设法转换第一次出现,但不知道如何设置可重复的条件。我删除了代码,因为它不起作用(我不记得我做了什么),但结果是这样的:
<dc_type xsi_type="TypeName" xsi:identifier="NN">Others</dc_type>
然而美丽的是:
<dc_type xsi_type="TypeName" xsi_identifier="NN">Others</dc_type>
那里有没有可以提供帮助的正则表达式大师?
答案 0 :(得分:4)
我一直在寻找相同的东西,但我知道最好不要尝试使用正则表达式来对抗XML(搜索任何关于使用正则表达式解析XML / HTML的StackOverfow问题并阅读整个答案以找出原因。你会当你看到它时就知道了!)
以下是我提出的代码:
<?php
// Some test XML
$xml = <<<XML
<root xmlns:a="bogus.a" xmlns:b="bogus.b">
<a:first>
<b:second>text</b:second>
</a:first>
</root>
XML;
$sxe = new SimpleXMLElement($xml);
$dom_sxe = dom_import_simplexml($sxe);
$dom = new DOMDocument('1.0');
$dom_sxe = $dom->importNode($dom_sxe, true);
$dom_sxe = $dom->appendChild($dom_sxe);
$element = $dom->childNodes->item(0);
// See what the XML looks like before the transformation
echo "<pre>\n" . htmlspecialchars($dom->saveXML()) . "\n</pre>";
foreach ($sxe->getDocNamespaces() as $name => $uri) {
$element->removeAttributeNS($uri, $name);
}
// See what the XML looks like after the transformation
echo "<pre>\n" . htmlspecialchars($dom->saveXML()) . "\n</pre>";
?>
答案 1 :(得分:1)
要重写完整的XML文档,例如重命名元素或属性名称以及更改名称空间相关数据(如xmlns
属性),您可以使用基于expat的xml解析器扩展:
这可以通过解析文件并动态更改输出来实现。解析器调用回调函数(所谓的 handler )来获取预解析的数据,例如字符串形式的元素名称和数组形式的属性。
然后,您可以动态更改这些值并输出(可能已更改的)数据。
通过这种方式,你不再需要关心正则表达式(这对于正确的XML解析来说是非常重要的)。
您可以在a previous answer of mine中找到一些样板代码来启动它。