Frost
Frost

Reputation: 13

Remove xmlns:fm from attributes

I know this kind of question has been answered multiple times, but all the solutions I could find since yesterday didn't work for me.

I have a first XSL file which transforms "custom" XML Framemaker files to DITA file. For some reasons, I have a second XSL file which "cleans" the DITA file obtained:

<?xml version="1.0" encoding="utf-8"?>
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

  <xsl:strip-space elements="*"/>

  <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
  </xsl:template>

  <xsl:template match="*[not(@*|*|comment()|processing-instruction()) and normalize-space()='']"/>

  <xsl:template match="//title/text()[normalize-space()]">
   <xsl:value-of select="normalize-space()"/>
  </xsl:template>

  <xsl:template match="//title/text()[not(normalize-space())]" />

  <xsl:template match="table//footnote"><fn><xsl:value-of select="."/></fn></xsl:template>

  <xsl:template match="//para"><p><xsl:value-of select="."/></p></xsl:template>

  </xsl:stylesheet>

Here's a snippet of the output XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE topic PUBLIC "-//OASIS//DTD DITA 1.2 Topic//EN" "../../dtd/technicalContent/dtd/topic.dtd">
<topic id="Interfaces">
<title>Interfaces</title>
<body>
  <table xmlns:fm="fctfmns.xml" frame="all" colsep="1" rowsep="1">
     <tgroup cols="2" colsep="1" rowsep="1" outputclass="General">
        <colspec colnum="1" colname="1" colwidth="34*"/>
        <colspec colnum="2" colname="2" colwidth="66*"/>
        <thead>

But the wanted output would be:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE topic PUBLIC "-//OASIS//DTD DITA 1.2 Topic//EN" "../../dtd/technicalContent/dtd/topic.dtd">
<topic id="Interfaces">
<title>Interfaces</title>
<body>
  <table frame="all" colsep="1" rowsep="1">
     <tgroup cols="2" colsep="1" rowsep="1" outputclass="General">
        <colspec colnum="1" colname="1" colwidth="34*"/>
        <colspec colnum="2" colname="2" colwidth="66*"/>
        <thead>

So I want the "attribute" xmlns:fm="fctfmns.xml" to be removed. But it seems like it's impossible with all the solutions I tried to include in the cleaning XSL:

<xsl:template match="@xmlns:fm">

doesn't work, and so do its derivates (with name()). I also tried to declare xmlns:fm in xsl:stylesheet and to exclude prefix fm, but it didn't work either.

The weirdest thing is that <xsl:template match="@*"> removes all the attributes, but not xmlns:fm.

EDIT :

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp "&#xa0;">]>

<chapter RSID-Document = "BasisRS://OBJ_DOKU/11//001/1//11:63"
RSKM-DocuType = "Manual" RSKM-ProductType = "x"
RSKM-ProductGroup = "x"
RSKM-ProductName = "x" RSIM-Status = "3"
RSKM-Language = "EN" chaptertype = "train" ActivateFilter = "Off">
<title
id = "P_12bcc27e" startposition = "topofpage">x</title>
<module id = "P_67912cfb" xmlns:fm = "fctfmns.xml"
RSID-Component = "BasisRS://OBJ_BAUST/906/EN/001/1//925:2"
RSIM-Checksum = "4ad808b1" RSIM-XRefID = "UID:906:3:9f1e5d1">
    <topic>
        <title id = "P_37e7a2f6" RSIM-XRefID = "UID:906:1:9f1e5c1">x</title>
        <table frame = "all" colsep = "1" rowsep = "1" id = "P_982c71a0"
RSIM-XRefID = "UID:906:2:9f1e5c1">
            <tgroup cols = "2" colsep = "1" rowsep = "1" outputclass = "General">
                <colspec colnum = "1" colname = "1" colwidth = "28*"/>
                <colspec colnum = "2" colname = "2" colwidth = "72*"/>
                <thead>
                    <row rowsep = "1">
                        <entry colname = "1">
                            <para>x</para>
                        </entry>
                        <entry colname = "2">
                            <para>x</para>
                        </entry>
                    </row>
                </thead>
                <tbody>
                    <row rowsep = "1">
                        <entry colname = "1">
                            <para>x</para>
                        </entry>
                        <entry colname = "2">
                            <para>x</para>
                        </entry>
                    </row>
                    <row rowsep = "1">
                        <entry colname = "1">
                            <para>x</para>
                        </entry>
                        <entry colname = "2">
                            <para>x</para>
                        </entry>
                    </row>
                    <row rowsep = "1">
                        <entry colname = "1">
                            <para>x</para>
                        </entry>
                        <entry colname = "2">
                            <para>x</para>
                        </entry>
                    </row>
                    <row rowsep = "1">
                        <entry colname = "1">
                            <para>x</para>
                        </entry>
                        <entry colname = "2">
                            <para>x</para>
                        </entry>
                    </row>
                    <row rowsep = "1">
                        <entry colname = "1">
                            <para>x</para>
                        </entry>
                        <entry colname = "2">
                            <para>x</para>
                        </entry>
                    </row>
                    <row rowsep = "1">
                        <entry colname = "1">
                            <para>x</para>
                        </entry>
                        <entry colname = "2">
                            <para>x</para>
                        </entry>
                    </row>
                    <row rowsep = "1">
                        <entry colname = "1">
                            <para>x</para>
                        </entry>
                        <entry colname = "2">
                            <para>x</para>
                        </entry>
                    </row>
                    <row rowsep = "0">
                        <entry colname = "1">
                            <para>x</para>
                        </entry>
                        <entry colname = "2">
                            <para>x</para>
                        </entry>
                    </row>
                </tbody>
            </tgroup>
        </table>
    </topic>
</module>
</chapter>

(Desired output is written above)

Please note that the xmlns:fm namespace is in the module element in the input, but depending on the solutions I test, the xmlns:fm namespace appears either in the table, topic, title, or most often in the tgroup element.

Upvotes: 1

Views: 539

Answers (2)

Martin Honnen
Martin Honnen

Reputation: 167696

Assuming you really use an XSLT 2.0 processor and the namespace declaration is copied from your input you can change the template

  <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
  </xsl:template>

to

  <xsl:template match="node()|@*">
  <xsl:copy copy-namespaces="no">
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
  </xsl:template>

See http://xsltransform.net/jyRYYhX for an example where the input has the namespace declaration while the output not because the xsl:copy copy-namespaces="no" has not copied it.

With XSLT 1.0 you can use

<xsl:template match="*">
  <xsl:element name="{name()}" namespace="{namespace-uri()}">
    <xsl:apply-templates select="@* | node()"/>
  </xsl:element>
</xsl:template>

<xsl:template match="@*">
  <xsl:attribute name="{name()}" namespace="{namespace-uri()}">
    <xsl:value-of select="."/>
  </xsl:attribute>
</xsl:template>

instead of

  <xsl:template match="node()|@*">
  <xsl:copy copy-namespaces="no">
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
  </xsl:template>

Upvotes: 1

michael.hor257k
michael.hor257k

Reputation: 117073

The problem with your approach is that you are copying the entire table as is - and this also copies all namespaces that are in scope at that point.

To avoid this, replace this:

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

with:

<xsl:template match="table"> 
    <xsl:apply-templates select="." mode="remove-namespaces"/>
</xsl:template> 

<xsl:template match="*" mode="remove-namespaces">
    <xsl:element name="{local-name()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates mode="remove-namespaces"/>
    </xsl:element>
</xsl:template>

Note: this is referring to the stylesheet you have posted at http://xsltransform.net/ncdD7kZ - which is very different from the one in your question.

Upvotes: 1

Related Questions