代码之家  ›  专栏  ›  技术社区  ›  thomasrutter

如何在phpdom中检测和删除不必要的xmlns:<something>属性?

  •  2
  • thomasrutter  · 技术社区  · 14 年前

    假设我有这样一个源文档:

    <element>
      <subelement xmlns:someprefix="mynamespace"/>
    </element>
    

    这个 xmlns:someprefix

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

    我知道我能读得懂 hasAttribute() removeAttributeNS() (奇怪)但前提是我知道它的前缀。它不会出现在 DOMNode->attributes

    我该怎么做?任何查询哪个名称空间(即什么)是否已在元素中声明?

    1 回复  |  直到 8 年前
        1
  •  1
  •   Community uzul    7 年前

    如何检测:

    <?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的afaik),并使用 XML Writer 函数,跳过未使用的命名空间声明。不是一个有趣的假期,所以我将留给你的实现。另一种选择 根据 this question ,但我怀疑它是否有用。我尽了最大努力似乎成功了,但是将“顶级”/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>
    

    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>