Merge two xml schemas using XSLT
I'm transforming an XML Schema using XSLT 2.0. The first schema (s1.xsd) imports a second schema (s2.xsd) as follows:
Content of s1.xsd
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema.xsd"
xmlns:ns1="URI1" targetNamespace="URI2"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<import namespace="URI1" schemaLocation="s2.xsd"/>
<element name="element1"/>
<element name="element2"/>
</schema>
and content of s2.xsd
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:ns1="URI1" targetNamespace="URI1">
<attribute name="attr1"/>
<schema>
My XSLT declares the XS namespace as follows:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.or开发者_开发技巧g/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
I would like to merge the nodes of s2.xsd into the <schema>-element of s1.xsd. So far, I've tried
<xsl:template name="merge_imported_schemas">
<xsl:for-each select="/schema/import[@namespace = //namespace::*]">
<!-- file exists? -->
<xsl:choose>
<xsl:when test="boolean(document(@schemaLocation))">
<!-- schema found -->
<xsl:copy-of select="document(@schemaLocation)/*/node()"/>
</xsl:when>
<xsl:otherwise>
<!-- schema not found -->
<xsl:message terminate="yes">
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
but I don't get the desired result. Could anyone please tell me what I'm doing wrong? I suspect there is a namespace-collision here, but honestly I find using namespaces a little confusing. Thanks!
You need to qualify the elements in your XPath. At the moment select="/schema/import[@namespace = //namespace::*]">
doesn't match anything at all, because there is no element /schema
. The XPath is trying to match elements with no namespace.
Change it to select="/xs:schema/xs:import[@namespace = //namespace::*]">
and it should work.
Remember, namespace prefixes are an alias for the namespace URI, and if you have a default namespace (as in your xsd files), elements with no prefix are still namespace-qualified.
As an aside, instead of <xsl:for-each select="/schema/import[@namespace = //namespace::*]">
, you might have more success using <xsl:apply-templates select="/xs:schema/node()"
, and defining different templates for the different kinds of node that you wish to copy into the output tree.
精彩评论