XSL转换从其他节点生成输出

时间:2010-03-12 00:41:47

标签: xml formatting xslt

我有以下XSL模板(我省略了组织模板,请告诉我是否有必要):

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">     
<xsl:output method="html" indent="yes" omit-xml-declaration="yes"/>

<xsl:template match="SOAP-ENV:Body/*[local-name()='Publisher']">
    <html>      
        <xsl:call-template name="body" />
    </html>     
</xsl:template>
    <xsl:template name="body">
    <BODY>
        <br/>
        <center>
            <font face="arial" size="2">
                <b>Publisher <xsl:value-of select="*[local-name()='Organization']/*[local-name()='PublisherData']/*[local-name()='PublisherName']"/>
                </b>
            </font>
        </center>
        <br/>
        <xsl:apply-templates select="*[local-name()='Organization']"/>
    </BODY>
</xsl:template>
</xsl:stylesheet>

上一个模板生成我想要的输出,它生成包含“body”模板生成的输出的标签。我遇到的问题是在开始标记之前我从前一个节点获得文本输出。不知道为什么会发生这种情况,因为我没有选择其他节点。例如:

<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <SOAP-ENV:Header>
            <n1>abc</n1>
                <n2>def</n2>
        </SOAP-ENV:Header>
        <SOAP-ENV:Body>
            <Publisher>
                          <!--Child nodes here -->
                    </Publisher>
            </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>

鉴于前面的示例XML片段,我的输出将包含我期望格式化Publisher元素的内容,但我也得到了SOAP-ENV:Header节点的子节点的文本节点。

我只想转换Publisher元素的内容,但在输出中我会得到:

abc
def
//Expected output transforming Publisher goes here

我的问题是,为什么选择abc和def?

1 个答案:

答案 0 :(得分:3)

正在生成输出,因为built in template rules

  • 将文本节点复制到输出
  • 将模板应用于元素

XSLT 1.0建议书的相关部分包含在下面。

您可能只想为SOAP-ENV:Header做一个无用的模板。

<xsl:template match="SOAP-ENV:Header">
</xsl:template>

源文档中的某些元素不在命名空间中。在XPath表达式中,没有名称空间的元素可以通过其文字本地名称引用。如果您不知道元素的命名空间,则只需使用local-name()

以下是样式表的修改版本。它以匹配/的模板开头,然后显式选择我们想要的节点。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">

    <xsl:output method="html" indent="yes" omit-xml-declaration="yes"/>

    <xsl:template match="/">
        <html>      
            <xsl:apply-templates select="SOAP-ENV:Body/Publisher" />
        </html>     
    </xsl:template>

    <xsl:template name="Publisher">
        <body>
            <br/>
            <center>
                <font face="arial" size="2">
                    <b>
                        <xsl:text>Publisher </xsl:text>
                        <xsl:value-of select="Organization/PublisherData/PublisherName"/>
                    </b>
                </font>
            </center>
            <br/>
            <xsl:apply-templates select="Organization"/>
        </body>
    </xsl:template>
</xsl:stylesheet>

内置模板规则

  

有一个内置的模板规则   允许递归处理继续   在没有成功模式的情况下   匹配显式模板规则   样式表。此模板规则   适用于两个元素节点和   根节点。以下显示了   相当于内置模板   规则:

<xsl:template match="*|/">
  <xsl:apply-templates/>
</xsl:template>
     

还有一个内置模板规则   对于每种模式,它允许递归   处理继续在同一个   模式在没有成功的情况下   模式匹配显式模板   样式表中的规则。这个模板   规则适用于两个元素节点和   根节点。以下显示了   相当于内置模板   模式m的规则。

<xsl:template match="*|/" mode="m">
  <xsl:apply-templates mode="m"/>
</xsl:template>
     

还有一个内置模板规则   对于文本和属性节点   通过以下方式复制文本:

<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>
     

内置模板规则   处理说明和评论   是什么都不做。

<xsl:template match="processing-instruction()|comment()"/>
     

内置模板规则   命名空间节点也无所作为。   没有可以匹配的模式   名称空间节点所以,内置   模板规则是唯一的模板   应用于命名空间的规则   节点

     

内置模板规则是   如同进口一样对待   隐式地在样式表之前和   因此导入优先级低于   所有其他模板规则。就这样   作者可以覆盖内置的   模板规则通过包含显式   模板规则。