Tim R
Tim R

Reputation: 31

XSLT copy an elements attributes unless attribute is in a given namespace

These are SVG elements, and the supplier of the SVG documents has added all kinds of extensions, that we can not use, and do not want. So I'd like these extended attributes removed.

I'm basically using the identity transform. I want this element:

<text id="1" 
      i:knockout="Off" 
      i:objectType="pointText" 
      style="font-size:16;"
     >Hi</text>

to copy as

<text id="1" style="font-size:16;">Hi</text>

Any help appreciated.

Edit

Unfortunately, the example I chose above wasn't a real one. This one is:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" 
     xmlns:i="http://ns.adobe.com/AdobeIllustrator/10.0/" 
     i:viewOrigin="-39.4106 906.6265" i:rulerOrigin="0 0" i:pageBounds="0 840 592 0" >
   <g i:extraneous="self">
   </g>
</svg>

and what I want is:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" 
     >
   <g>
   </g>
</svg>

Upvotes: 1

Views: 486

Answers (1)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243579

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="*">
  <xsl:element name="{name()}" namespace="{namespace-uri()}">
   <xsl:copy-of select=
    "namespace::*[not(.='i:i')]"/>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="@*[namespace-uri()='i:i']"/>

 <xsl:template match="@*">
  <xsl:copy-of select="."/>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<text id="1" xmlns:i="i:i"
  i:knockout="Off"
  i:objectType="pointText"
  style="font-size:16;">Hi</text>

produces the wanted, correct result:

<text id="1" style="font-size:16;">Hi</text>

UPDATE: The OP now has specified the exact namespace he has the prefix "i" bound to.

In this case a simple replace of "i:i" with http://ns.adobe.com/AdobeIllustrator/10.0/ gives us the new solution:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:param name="pUnwantedNS" select="'http://ns.adobe.com/AdobeIllustrator/10.0/'"/>

    <xsl:template match="*">
        <xsl:element name="{name()}" namespace="{namespace-uri()}">
            <xsl:copy-of select="namespace::*[not(.=$pUnwantedNS)]"/>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="@*">
        <xsl:copy-of select="."/>
    </xsl:template>

    <xsl:template match=
    "@*[namespace-uri()='http://ns.adobe.com/AdobeIllustrator/10.0/']"/>
</xsl:stylesheet>

and when applied on the newly-provided XML document:

<svg xmlns="http://www.w3.org/2000/svg"
  xmlns:i="http://ns.adobe.com/AdobeIllustrator/10.0/"
  i:viewOrigin="-39.4106 906.6265"
  i:rulerOrigin="0 0"
  i:pageBounds="0 840 592 0" >
    <g i:extraneous="self"></g>
</svg>

the wanted, correct result is again produced:

<svg xmlns="http://www.w3.org/2000/svg">
  <g />
</svg>

Upvotes: 0

Related Questions