XSLT包含不同的命名空间

时间:2017-11-23 08:58:42

标签: xml xslt xsd

我遇到了XSLT混合命名空间的问题。我想为命名空间“doc”中的不同项目创建一些共享模板,并从名称空间“map”中调用它们,但这不起作用。有没有办法做到这一点?

map.xml:

<?xml version="1.0"?>
<root xmlns="http://www.example.com/map"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.example.com/map map.xsd">
    <node>
        <short>Short description</short>
        <long>Long description <br/> needs a lot of space</long>
    </node>
    <node>
        <short>Another short description</short>
        <long>Another long description <br/> also needs a lot of space_</long>
    </node>
</root>

map.xsd

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.example.com/map"
    xmlns:tns="http://www.example.com/map"
    xmlns:doc="http://www.example.com/doc"
    elementFormDefault="qualified">
    <import namespace="http://www.example.com/doc" schemaLocation="doc.xsd"/>

    <element name="root">
        <complexType>
            <sequence>
                <element name="node" minOccurs="1" maxOccurs="unbounded">
                    <complexType>
                        <sequence>
                            <element name="short" type="normalizedString" />
                            <element name="long">
                                <complexType mixed="true">
                                    <sequence>
                                        <choice minOccurs="0" maxOccurs="unbounded">
                                            <element ref="doc:br" />
                                        </choice>
                                    </sequence>
                                </complexType>    
                            </element>
                        </sequence>
                    </complexType>
                </element>
            </sequence>
        </complexType>
    </element>

    <!-- make imported elements from documentation public available -->
    <element name="br" substitutionGroup="doc:br"/>
</schema>

doc.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.example.com/doc"
    xmlns:tns="http://www.example.com/doc"
    elementFormDefault="qualified">

    <element name="br"></element>
</schema>

xml文件使用此架构文件进行验证。

map.xsl:

<?xml version="1.0"?>
<xsl:transform version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.w3.org/1999/XSL/Transform http://www.w3.org/2007/schema-for-xslt20.xsd"
    xmlns:doc="http://www.example.com/doc"
    xmlns:map="http://www.example.com/map" >
    <xsl:import href="doc.xsl" />

    <!-- output method is .tex file, no xml -->
    <xsl:output method="text" media-type="application/x-tex" indent="no"/>

    <xsl:template match="map:root">
        <xsl:text>\begin{Root}{&#xd;&#xa;</xsl:text>
        <xsl:apply-templates select="map:node" />
        <xsl:text>\end{Root}</xsl:text>
    </xsl:template>

    <xsl:template match="map:node">
        <xsl:text>\begin{Node}&#xd;&#xa;{</xsl:text>
        <xsl:apply-templates select="map:short" />
        <xsl:text>}&#xd;&#xa;</xsl:text>
        <xsl:apply-templates select="map:long" />
        <xsl:text>&#xd;&#xa;\end{Node}&#xd;&#xa;</xsl:text>
    </xsl:template>

    <xsl:template match="map:short">
        <xsl:apply-templates select="text()" />
    </xsl:template>

    <xsl:template match="map:long">
        <xsl:apply-templates select="text() | doc:br" />
    </xsl:template>
</xsl:transform>

doc.xsl:

<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.w3.org/1999/XSL/Transform http://www.w3.org/2007/schema-for-xslt20.xsd"
    xmlns:doc="http://www.example.com/doc" >    

    <xsl:template match="doc:br">
        <xsl:text> \\&#xd;&#xa;</xsl:text>
    </xsl:template>

    <!-- copy unspecific text, escape before -->
    <xsl:template match="text()">
        <xsl:copy-of select="normalize-space(replace(., '(&amp;|%|\$|#|_)', '\\$1'))" />
    </xsl:template>
</xsl:stylesheet>

使用此模板,转换有效,但不会产生病变输出。

生成输出:

\begin{Root}{
\begin{Node}
{Short description}
Long description needs a lot of space
\end{Node}
\begin{Node}
{Another short description}
Another long description also needs a lot of space\_
\end{Node}
\end{Root}

期望的输出:

\begin{Root}{
\begin{Node}
{Short description}
Long description needs a lot of space
\end{Node}
\begin{Node}
{Another short description}
Another long description also \\
needs a lot of space\_
\end{Node}
\end{Root}

2 个答案:

答案 0 :(得分:1)

根据您的map.xml输入文档,该文档中的所有元素都位于同一名称空间http://www.example.com/map中,包括br元素。因此,我不明白为什么导入的样式表与不同命名空间中的br元素匹配应该有助于该输入文档。如果要转换这些元素,则需要编写匹配map:br的模板。

答案 1 :(得分:0)

根据XSLT include with different namespaces我修改了doc.xsl:

<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.w3.org/1999/XSL/Transform http://www.w3.org/2007/schema-for-xslt20.xsd"
    xmlns:doc="http://www.example.com/doc" >    

    <xsl:template match="*:br">
        <xsl:text> \\&#xd;&#xa;</xsl:text>
    </xsl:template>

    <!-- copy unspecific text, escape before -->
    <xsl:template match="text()">
        <xsl:copy-of select="normalize-space(replace(., '(&amp;|%|\$|#|_)', '\\$1'))" />
    </xsl:template>
</xsl:stylesheet>

另一种可能性是使用命名模板,然后按照他的建议从主xsl文件中调用它们。

相关问题