1

我最近对 ​​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>

有没有正则表达式大师可以提供帮助?

4

2 回答 2

5

我一直在寻找同样的东西,但我知道最好不要尝试对 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>";
?>
于 2013-09-25T01:36:40.040 回答
1

要重写完整的 XML 文档,例如重命名元素或属性名称以及更改与名称空间相关的数据(例如xmlns属性),您可以使用基于 expat 的 xml 解析器扩展:

这通过解析文件并动态更改输出来工作。解析器调用回调函数(所谓的handler)来获取预先解析的数据,例如字符串形式的元素名称和数组形式的属性。

然后,您可以即时更改这些值并输出(可能更改的)数据。

通过这种方式,您不再需要关心正则表达式(这对于正确的 XML 解析来说很重要)。

您可以在我以前的回答中找到一些样板代码来开始此操作。

于 2013-03-05T12:28:56.523 回答