摆脱XSL模板输出中的XML根节点

时间:2009-06-22 23:10:47

标签: xml xslt xhtml

我使用XSL模板作为Web框架的网页模板,最终输出为XHTML 1.0 Strict;它需要XML输入并输出XHTML。它完美地工作除了一个问题 - 结束输出也输出XML节点而不仅仅是内容。这是基本的XML(缺少一些项目,但总体设计是相同的):

<Page>
    <PageScript>
        <Script>./js/myscript.js</Script>
    </PageScript>
    <PageCSS>
        <CSS>./css/mycss.css</CSS>
    </PageCSS>
    <PageContent>Blah blah blah</PageContent>
</Page>

这是XSL模板

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:response="http://www.ntforl.com/"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xhtml="http://www.w3.org/1999/xhtml"
    xmlns:lang="en">

    <xsl:output
        method="xml"
        doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
        doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
    />

    <xsl:template match="//PageCSS">
        <xsl:for-each select="CSS">
            <link type="text/css" rel="stylesheet">
                <xsl:attribute name="href">
                    <xsl:value-of select="." />
                </xsl:attribute>
            </link>
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="//PageScript">
        <xsl:for-each select="Script">
            <script type="text/javascript">
                <xsl:attribute name="src">
                    <xsl:value-of select="." />
                </xsl:attribute>
            </script>
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/" disable-output-escaping="yes">
        <html>
            <head>
                <title>
                    <xsl:value-of select="//PageTitle" />
                </title>
                <meta http-equiv="content-type" content="text/html;charset=utf-8" />
                <link type="text/css" rel="stylesheet" href="template/style/globalStyle.css" />
                <link type="text/css" rel="stylesheet" href="template/style/standards.css" />
                <xsl:apply-templates select="//PageCSS" />
                <script type="text/javascript" src="template/js/some_file.js"></script>
                <xsl:apply-templates select="//PageScript" />
            </head>
            <body onload="">
                <div id="container">
                    <div id="top">
                        <div class="clear" />
                    </div>
                    <div id="main">
                        <div class="left" style="width: 708px; margin-top: 10px;">
                            <h1 class="center">
                                <xsl:value-of select="//PageTitle" />
                            </h1>
                        </div>
                        <div class="clear" />
                        <div id="rightPane">
                            <div id="rightPaneContent">
                                <xsl:apply-templates select="//PageContent" />
                            </div>
                            <img src="template/images/mainBgBottom.png" alt="" />
                        </div>
                    </div>
                </div>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

问题在于PageContent,它只发生在PageContent上。运行转换时,模板输出

<PageContent xmlns=""> node content </PageContent>

在XHTML中。我需要知道如何摆脱它,以便我可以拥有一个有效的XHTML 1.0 Strict文档。

奇怪的是,PageContent节点是唯一执行此操作的节点,没有其他节点获取包含输出中节点名称的内容。这种行为的原因是什么?

3 个答案:

答案 0 :(得分:3)

您在apply-templates节点上呼叫PageContent

<xsl:apply-templates select="//PageContent" />

与此匹配的唯一模板是此模板,因此PageContent节点被复制:

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
</xsl:template>

可能你应该添加另一个匹配PageContent的模板,只处理子节点,而不复制PageContent本身:

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

答案 1 :(得分:2)

我会尝试将<xsl:apply-templates select="//PageContent" />替换为:

<xsl:apply-templates select="//PageContent/node()" />

答案 2 :(得分:2)

正如@sth和@molf已经指出的那样,您将获得由您的身份模板(<xsl:template match="@*|node()">)复制的节点,因为样式表中没有其他模板与<PageContent>个节点匹配。

作为其他两个解决方案已经提供的解决方案的替代方案,您可以将身份模板更改为:

<xsl:template match="@*|node()[not(self::PageContent)]">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()" />
  </xsl:copy>
</xsl:template>

现在遇到<PageContent>时,身份模板不再匹配。将使用隐式的元素默认模板,即:

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

这意味着模板将自动应用于<PageContent>个孩子,而本身节点不会被复制 - 只是你想要的。