Reputation: 3528
Why does the following not work as I'd expect it to?
<root xmlns:ns0="xmlns"
ns0:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ns1="xsi"
ns1:schemaLocation="[some schema location]" />
Basically, I'm trying to add schemaLocation to an xml file that doesn't have this by doing :-
<xsl:template match="/s:*">
<xsl:element name="{local-name()}" namespace="some other namespace">
<xsl:attribute namespace="xmlns" name="xsi">http://www.w3.org/2001/XMLSchema-instance</xsl:attribute>
<xsl:attribute namespace="xsi" name="schemaLocation">[some-loc]</xsl-attribute>
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
and Xalan-C gives the xml shown above.
What I'm trying to get is something like :-
<root xmlns:ns0="http://www.w3.org/2001/XMLSchema-instance"
ns0:schemaLocation="[some schema location]" />
Upvotes: 0
Views: 921
Reputation: 9863
You need <xsl:attribute name="xsi:schemaLocation">[some-loc]</xsl:attribute>
.
Edit (adding complete example):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="root">
<xsl:element name="{local-name()}" namespace="some other namespace">
<!--<xsl:attribute namespace="xmlns" name="xsi">http://www.w3.org/2001/XMLSchema-instance</xsl:attribute>-->
<xsl:attribute name="xsi:schemaLocation">[some-loc]</xsl:attribute>
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Depending on what exactly you're doing you can possibly use <xsl:copy>
to copy the element instead of <xsl:element name="{local-name()}"/>
; it's somewhat simpler.
Upvotes: 3
Reputation: 27996
As I'm interpreting your question and inferring what you actually wanted, the problem is that you are putting a value in namespace="..."
that you intend to be a namespace prefix, but is actually supposed to be a namespace URI.
Thus the code you probably want is just one <xsl:attribute>
element:
<xsl:template match="/s:*">
<xsl:element name="{local-name()}" namespace="some other namespace">
<xsl:attribute namespace="http://www.w3.org/2001/XMLSchema-instance"
name="xsi:schemaLocation">[some-loc]</xsl-attribute>
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
Then the XSLT processor will output the specified schemaLocation
attribute in the right namespace, and will also emit a namespace declaration for its prefix where needed (and its prefix may be xsi:
, but doesn't have to be).
Part of the problem here is that people throw around the word "namespace" (mentally or to others) without being clear about what they mean. A namespace is not a namespace prefix, nor is it really a namespace URI. A namespace is globally identified by its URI, and locally identified by its prefix.
If the XSLT spec had named this attribute namespace-uri="..."
instead of namespace="..."
, fewer people would fall into this trap. You can also protect yourself by asking whether someone who says "namespace" really means "namespace URI", "namespace prefix", "namespace declaration", etc. etc.
Upvotes: 3