【问题标题】:Get rid of XML root node in XSL template output去掉 XSL 模板输出中的 XML 根节点
【发布时间】:2010-11-05 00:24:08
【问题描述】:

我正在使用 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 节点是唯一执行此操作的节点,没有其他节点将其内容与输出中的节点名称包装在一起。这种行为的原因是什么?

【问题讨论】:

    标签: xml xslt xhtml


    【解决方案1】:

    您在PageContent 节点上调用apply-templates

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

    【讨论】:

    • 谢谢大家,这些非常有帮助。不过,我还有另一个问题。这些摆脱了父节点问题,但 PageContent 内的第一个节点获得了xlmns="" 属性,我很好奇是否可以以任何方式留下。如果这有帮助,PageContent 节点会保存 xhtml——它基本上是 xhtml 中页面的主要部分——运行用户请求的任何进程的结果。
    【解决方案2】:

    我会尝试将&lt;xsl:apply-templates select="//PageContent" /&gt; 替换为:

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

    【讨论】:

      【解决方案3】:

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

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

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

      现在遇到&lt;PageContent&gt; 时,标识模板不再匹配。将使用元素的隐式默认模板,即:

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

      这意味着模板将自动应用于&lt;PageContent&gt; 的子节点,并且不会复制节点本身 - 这正是您想要的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-03-18
        • 1970-01-01
        • 1970-01-01
        • 2019-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多