php - 如何检测和删除不必要的 xmlns :<something> attributes in PHP DOM?

标签 php xml dom namespaces xml-namespaces

假设我有一个这样的源文件:

<element>
  <subelement xmlns:someprefix="mynamespace"/>
</element>
xmlns:someprefix显然这里不需要并且不做任何事情,因为该前缀没有在该元素中使用(或者在我的情况下,在文档中的任何地方)。

在 PHP 中,在我使用 DOMDocument->loadXML() 将它加载到 DOM 树后,我希望能够检测到这样的命名空间声明存在,并将其删除。

我知道我可以用 hasAttribute() 阅读它甚至用 removeAttributeNS() 删除它(奇怪)但前提是我知道它的前缀。它没有出现在 DOMNode->attributes根本没有,因为我试图找到的东西不被视为属性。除了将其序列化回 XML 字符串并运行正则表达式或其他东西之外,我看不到任何检测它是否存在的方法。

我该怎么做?有什么方法可以查询元素中声明了哪些命名空间(即 xmlns:something)?

最佳答案

如何检测:

<?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;
}

如何删除:pff,我知道你唯一的选择是使用 xml_parse_into_struct() (因为这不是依赖于 libxml2 的 afaik),并使用 XML Writer 循环遍历结果数组函数,跳过未使用的命名空间声明。不是一个有趣的消遣,所以我会把实现留给你。根据 this question,另一种选择可能是 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>

使用 xsl (namespaces & not() 子句基于之前的 $used 数组,所以你仍然需要那个 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>

关于php - 如何检测和删除不必要的 xmlns :<something> attributes in PHP DOM?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3810569/

相关文章:

php - 从 Drupal 7 中的模块调用 $site_name 变量

PHP缓存sql结果

java - 当节点也有内部节点时,有没有办法映射该节点的值?

javascript - 向 DOM 元素添加非标准属性是一种不好的做法吗? - HTML/Javascript

javascript - 如何制作在单击时递增和递减值的按钮?

javascript - 更改 div 类 onclick --- 并*保存*更改

javascript - 想要使用提交处理程序

javascript - 在 Angular js文件中获取未定义的php值

xml - XPath 或 XML 内容中的上下文概念是什么

xml - 需要使用 XSLT 从 XML 输出文本节点的帮助