说我有这样的源文档:
<element>
<subelement xmlns:someprefix="mynamespace"/>
</element>
这里显然不需要xmlns:someprefix
并且不做任何事情,因为该元素中没有使用该前缀(或者在我的情况下,在文档中的任何地方)。
在PHP中,在我使用DOMDocument-&gt; loadXML()将其加载到DOM树之后,我希望能够检测到存在这样的命名空间声明,并将其删除。
我知道我可以用hasAttribute()
阅读它,甚至用removeAttributeNS()
删除它(奇怪的是),但前提是我知道它的前缀。它根本没有出现在DOMNode->attributes
中,因为我试图找到的东西不被视为属性。除了将其序列化回XML字符串并运行正则表达式之外,我看不出有任何方法可以在不知道前缀的情况下检测它是否存在。
我该怎么办?查询哪些命名空间(即xmlns:something)已在元素中声明的任何方法?
答案 0 :(得分:1)
如何检测:
<?php
$d = new DOMDocument();
$d->loadXML('
<element>
<subelement xmlns:someprefix="http://mynamespace/asd">
</subelement>
</element>');
$sxe = simplexml_import_dom($d);
$namespaces = $sxe->getDocNamespaces(true);
$x = new DOMXpath($d);
foreach($namespaces as $prefix => $url){
$count = $x->evaluate("count(//*[namespace-uri()='".$url."' or @*[namespace-uri()='".$url."']])");
echo $prefix.' ( '.$url.' ): used '.$count.' times'.PHP_EOL;
}
如何删除:pfff,关于我所知道的唯一选项是使用xml_parse_into_struct()
(因为这不是libxml2 reliant afaik),并使用XML Writer
函数循环生成的数组,跳过未使用的名称空间声明。这不是一个有趣的传递时间,所以我将把实现留给你。根据{{3}},另一个选项可以是XSL,但我怀疑它有多大用处。我的最大努力似乎取得了成功,但将“顶级”/ rootnode命名空间移动到了子级,导致更加混乱。
修改:这似乎有效:
给定XML(添加了一些名称空间混乱):
<element xmlns:yetanotherprefix="http://mynamespace/yet">
<subelement
xmlns:someprefix="http://mynamespace/foo"
xmlns:otherprefix="http://mynamespace/bar"
foo="bar"
yetanotherprefix:bax="foz">
<otherprefix:bar>
<yetanotherprefix:element/>
<otherprefix:element/>
</otherprefix:bar>
<otherprefix:bar>
<yetanotherprefix:element/>
<otherprefix:element/>
</otherprefix:bar>
<yetanotherprefix:baz/>
</subelement>
使用基于以前$ used数组的xsl(名称空间和not()
子句,所以你仍然需要afaik。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:yetanotherprefix="http://mynamespace/yet"
xmlns:otherprefix="http://mynamespace/bar">
<xsl:template match="/">
<xsl:apply-templates select="/*"/>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{name(.)}">
<xsl:apply-templates select="./@*"/>
<xsl:copy-of select="namespace::*[not(name()='someprefix')]"/>
<xsl:apply-templates select="./node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
结果:
<?xml version="1.0"?>
<element xmlns:yetanotherprefix="http://mynamespace/yet">
<subelement xmlns:otherprefix="http://mynamespace/bar" foo="bar" yetanotherprefix:bax="foz">
<otherprefix:bar>
<yetanotherprefix:element/>
<otherprefix:element/>
</otherprefix:bar>
<otherprefix:bar>
<yetanotherprefix:element/>
<otherprefix:element/>
</otherprefix:bar>
<yetanotherprefix:baz/>
</subelement>
</element>