使用XSLT合并两个xml架构

时间:2010-05-20 12:34:21

标签: xslt schema merge-replication

我正在使用XSLT 2.0转换XML Schema。第一个模式(s1.xsd)导入第二个模式(s2.xsd),如下所示:

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>

和s2.xsd的内容

<schema xmlns="http://www.w3.org/2001/XMLSchema"
    xmlns:ns1="URI1" targetNamespace="URI1">
    <attribute name="attr1"/>
<schema>

我的XSLT声明XS名称空间如下:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">  

我想将s2.xsd的节点合并到s1.xsd的&lt; schema&gt; -element中。到目前为止,我已经尝试了

<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>

但我没有得到理想的结果。谁能告诉我我做错了什么?我怀疑这里存在命名空间冲突,但老实说,我发现使用命名空间有点令人困惑。谢谢!

1 个答案:

答案 0 :(得分:2)

您需要限定XPath中的元素。目前select="/schema/import[@namespace = //namespace::*]">根本不匹配任何内容,因为没有元素/schema。 XPath尝试将元素与 no 命名空间匹配。

将其更改为select="/xs:schema/xs:import[@namespace = //namespace::*]">,它应该有效。

请记住,名称空间前缀是名称空间URI的别名,如果您有默认名称空间(如在xsd文件中),则没有前缀的元素仍然是名称空间限定的。

除此之外,您可以使用<xsl:for-each select="/schema/import[@namespace = //namespace::*]">取得更多成功,并为要复制到输出树中的不同类型的节点定义不同的模板,而不是<xsl:apply-templates select="/xs:schema/node()"