How to detect and remove unnecessary xmlns: attributes in PHP DOM?

前端 未结 1 1846
不知归路
不知归路 2020-12-18 14:07

Say I have a source document like this:


  

The x

相关标签:
1条回答
  • 2020-12-18 14:55

    How to detect:

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

    How to remove: pfff, about your only option that I know of is to use xml_parse_into_struct() (as this is not libxml2 reliant afaik), and looping through the resulting array with XML Writer functions, skipping namespace declarations which are not used. Not a fun passtime, so I'll leave the implementation up to you. Another option could be XSL according to this question, but I doubt it is of much use. My best effort seems to succeed, but moves 'top-level'/rootnode namespaces to children, resulting in even more clutter.

    edit: this seems to work:

    Given XML (added some namespace clutter):

    <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>
    

    With xsl (namespaces & not() clause based on previous $used array, so you'll still need that 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>
    

    Results in:

    <?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>
    
    0 讨论(0)
提交回复
热议问题