I have an xml file where I need to rename elements. (also later to transform elements to attributes). The xslt transform inserts the default namespace into all the top level elements. I don't want that. I have seen quite a number of questions about this problem but still having issues with the desired result and understanding why...
- The best I can do with exclude-result-prefixes is:
<ar xmlns="">
<dyu xmlns="http://www.coastsystems.net">ábada</dyu>
Why is the namespace removed from only ar? And why does it preserve the xmlns=""?
- If i remove the renaming portion of the transform so it basically just copies the original file:
<xsl:template match="/c:lexique/c:headword">
<ar>
<xsl:apply-templates select="@* | node()"/>
</ar>
</xsl:template>
then 'exclude-result-prefixes' seems to have no effect at all. Whether its there or not there is no namespace inserted. Why?
Is there a hitch with xslt3? I need to use this as it handles the latin extended characters and sorting correctly.
The xml is as follows:
<?xml version='1.0' encoding='utf-8'?>
<lexique xmlns="http://www.coastsystems.net"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.coastsystems.net headwords2.xsd"
>
<headword>
<dyu>ábada</dyu>
<alt>abada</alt>
<emp></emp>
<cf>fewu</cf>
<trans>
<lang>fr</lang>
<detail></detail>
<speech>
<type></type>
<t-uuid>7b8612bc-23c7-4241-817f-f6fcd9bff8ac</t-uuid>
<def>
<gloss>jamais</gloss>
<gl-id>bbc05aae-8f08-4ab7-91ae-3b52533a896f</gl-id>
<note2></note2>
<note3></note3>
<note4></note4>
<tags></tags>
<example>
<source>a tɛ koɲuman kɛ abada.</source>
<target>Il ne fait jamais quelque chose de bien.</target>
<ex-id>2c592b68-0d29-4b6c-8614-005adab4fba5</ex-id>
</example>
</def>
</speech>
</trans>
</headword>
</lexique>
With the xslt stylesheet:
<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns:c="http://www.coastsystems.net"
exclude-result-prefixes="xsl c"
>
<xsl:output method="xml" indent="yes" encoding="UTF-8" />
<xsl:template match="/">
<xsl:apply-templates select="@*|node()"/>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/c:lexique/c:headword">
<ar>
<xsl:apply-templates select="@* | node()"/>
</ar>
</xsl:template>
</xsl:stylesheet>
(xslt3 -xsl:rename.xsl -s:headwords.xml)
Outputs:
<?xml version="1.0" encoding="UTF-8"?>
<lexique xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.coastsystems.net" xsi:schemaLocation="http://www.coastsystems.net headwords2.xsd">
<ar xmlns="">
<dyu xmlns="http://www.coastsystems.net">ábada</dyu>
<alt xmlns="http://www.coastsystems.net">abada</alt>
<emp xmlns="http://www.coastsystems.net"/>
<cf xmlns="http://www.coastsystems.net">fewu</cf>
<trans xmlns="http://www.coastsystems.net">
<lang>fr</lang>
<detail/>
<speech>
<type/>
<t-uuid>7b8612bc-23c7-4241-817f-f6fcd9bff8ac</t-uuid>
<def>
<gloss>jamais</gloss>
<gl-id>bbc05aae-8f08-4ab7-91ae-3b52533a896f</gl-id>
<note2/>
<note3/>
<note4/>
<tags/>
<example>
<source>a tɛ koɲuman kɛ abada.</source>
<target>Il ne fait jamais quelque chose de bien.</target>
<ex-id>2c592b68-0d29-4b6c-8614-005adab4fba5</ex-id>
</example>
</def>
</speech>
</trans>
</ar>
Desired output:
<?xml version="1.0" encoding="UTF-8"?>
<lexique xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.coastsystems.net" xsi:schemaLocation="http://www.coastsystems.net headwords2.xsd">
<ar>
<dyu>ábada</dyu>
<alt>abada</alt>
<emp/>
<cf>fewu</cf>
<trans>
<lang>fr</lang>
<detail/>
===== snipped
CodePudding user response:
The instruction to exclude-result-prefixes
only excludes them if they aren't used. If you want those other elements to be produced without a namespace, then you need to create elements without a namespace(using the local-name()
), instead of using xsl:copy
.
You can achieve this by adding a generic template for any element (following the identity template that is matching @*|node()
so that it has a higher priority match.
If you want all of the elements bound to the `` namespace, but not with a prefix, then set the default namespace in the stylesheet xmlns="http://www.coastsystems.net"
:
<xsl:stylesheet version="2.0"
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.coastsystems.net"
xmlns:c="http://www.coastsystems.net"
exclude-result-prefixes="xsl c"
>
<xsl:output method="xml" indent="yes" encoding="UTF-8" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="/c:lexique/c:headword">
<ar>
<xsl:apply-templates select="@* | node()"/>
</ar>
</xsl:template>
</xsl:stylesheet>
You could also change the match expression for the identity template to list the specific node()
and not include *
: @*|text()|comment()|processing-instruction()
.