Home > Software design >  XSLT Avoid namespace in element
XSLT Avoid namespace in element

Time:07-07

I met issue when trying to remove namespace in element tag. It is always display in element tag, but other tag is not display I also use exclude-result-prefixes but it is not work. I dont know that is the reason Please help to support to check this issue and explain how does it work Thank you

XML sample

<STATUS
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="MOM.Production">
    <A>
        <A1 CODE="11111" DESC="RAW" >
            <A2>
                <A2_ITEM NUMBER="DUM20000001" REVISION="01"  />
                <A2_ITEM NUMBER="DUM20000002" REVISION="01" />
            </A2>
        </A1>
        <A1 CODE="22222" DESC="POI" >
            <A2>
                <A2_ITEM NUMBER="DUM20000003" REVISION="01"  />
                <A2_ITEM NUMBER="DUM20000004" REVISION="01" />
            </A2>
        </A1>
    </A>
    <B>
        <B1 ID="A10" >A101</B1>
        <B1 ID="A12" >A121</B1>
        <B1 ID="A13" >A132</B1>
    </B>
</STATUS>

XSLT sample

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:mom="MOM.Production" exclude-result-prefixes="mom" >
    <xsl:output encoding="UTF-8" indent="yes" method="xml" version="1.0" />
    <xsl:template match="/mom:STATUS">
        <xsl:element name="Telegram">
            <xsl:element name="Body">
                <xsl:apply-templates select="/mom:STATUS/mom:A"/>
                <xsl:apply-templates select="/mom:STATUS/mom:B"/>
            </xsl:element>
        </xsl:element>
    </xsl:template>
    <xsl:template match="/mom:STATUS/mom:A">
        <xsl:element name="A">
            <xsl:copy-of select="*" />
        </xsl:element>
    </xsl:template>
    <xsl:template match="/mom:STATUS/mom:B">
        <xsl:element name="Options">
            <xsl:for-each select="/mom:STATUS/mom:B/mom:B1">
                <xsl:element name="Option">
                    <xsl:attribute name="code">
                        <xsl:value-of select="text()"/>
                    </xsl:attribute>
                    <xsl:attribute name="family">
                        <xsl:variable name="n">
                            <xsl:number/>
                        </xsl:variable>
                        <xsl:value-of select="$n - 1"/>
                    </xsl:attribute>
                </xsl:element>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Expect result

<Telegram>
    <Body>
        <A>
            <A1
             CODE="11111"
             DESC="RAW">
                <A2>
                    <A2_ITEM NUMBER="DUM20000001" REVISION="01"/>
                    <A2_ITEM NUMBER="DUM20000002" REVISION="01"/>
                </A2>
            </A1>
            <A1
             CODE="22222"
             DESC="POI">
                <A2>
                    <A2_ITEM NUMBER="DUM20000003" REVISION="01"/>
                    <A2_ITEM NUMBER="DUM20000004" REVISION="01"/>
                </A2>
            </A1>
        </A>
        <Options>
            <Option code="A101" family="0"/>
            <Option code="A121" family="1"/>
            <Option code="A132" family="2"/>
        </Options>
    </Body>
</Telegram>

CodePudding user response:

The attribute exclude-result-prefixes only affects the namespaces generated by a literal result element, and there are no literal result elements in your stylesheet.

The xsl:copy-of instruction copies element nodes unchanged from the input to the output. "Unchanged" means that the fully qualified name of the element (local-name plus namespace) is unchanged from the input. To change the names of the elements, you need to process the input recursively using apply-templates to change each element as it is encountered.

CodePudding user response:

I believe you are missing the fact that a default namespace declaration applies to all elements in its scope - in your case, to all elements in the entire XML document.

That means you cannot copy any elements; instead, you must recreate every element as a new element in no-namespace (this is equivalent to renaming all elements).

Try:

XSLT 1.0

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:mom="MOM.Production" 
exclude-result-prefixes="mom">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/mom:STATUS">
    <Telegram>
        <Body>
            <xsl:apply-templates/>
        </Body>
    </Telegram>
</xsl:template>
    
<xsl:template match="*">
    <xsl:element name="{local-name()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

<xsl:template match="mom:B">
    <Options>
        <xsl:apply-templates/>
    </Options>
</xsl:template>

<xsl:template match="mom:B1">
    <Option code="{.}" family="{position() - 1}"/>
</xsl:template>

</xsl:stylesheet>
  • Related