如何使用XSL在XML文档中打印元素标签

Coc*_*ola 0 xml xslt xslt-2.0 xslt-1.0

非常适合XSL的初学者.我正在尝试将2个XML文档转换为新的XML文档.我似乎无法将标签打印到新文档.只打印元素的内容.

XML

<books>
  <book>
    <name>Cat in the Hat</name>
    <author>Me</name>
    ...
    ...
  </book>
  ...
  ...
</book>
Run Code Online (Sandbox Code Playgroud)

XSL

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method = "xml" indent = "yes" /> 

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

    <xsl:element name="books">
        <xsl:template match="books">
            <xsl:element name="book">
                <xsl:for-each select="book">
                    <xsl:element name="name"><xsl:value-of select="name"/></xsl:element>
                    <xsl:element name="author"><xsl:value-of select="author"/></xsl:element>
                </xsl:for-each>
            </xsl:element>
        </xsl:template>
    </xsl:element>

</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

输出到XML文件Cat Hat in Hat Me

我需要输出为:

<books>
  <book>
    <name>Cat in the Hat</name>
    <author>Me</author>
  </book>
</books>
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

Tim*_*m C 5

严格来说,当你运行输出时,你实际上会遇到错误,因为MathiasMuller在评论中说,xsl:element不能是顶级元素(即它不能是直接的子元素xsl;stylesheet).我猜Ecplise可能只是忽略了这一点.

但是,如果您只获得文本输出,那是因为XSLT的内置模板规则,当XML中没有任何匹配的模板时,这些规则将用于匹配XML中的节点.实际上,这些只会跳过元素,最终输出他们找到的任何文本节点.

如果你确实想要以与输入相同的输出开始(这实际上是一种明智的方法,如果最终你只想改变部分XML),你应该从XSLT身份模板开始,该模板在其自己的副本上所有节点和属性按原样(并且意味着不会使用内置模板).

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes" />

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:transform>
Run Code Online (Sandbox Code Playgroud)

然后,当您想要对输出进行更改时,您只需要为要更改的节点/属性编写模板.例如,假设您有一个date希望从book元素下删除的元素,那么您只需添加此模板

<xsl:template match="date" />
Run Code Online (Sandbox Code Playgroud)

或者,也许你要重命名nametitle那么你可以这样做

<xsl:template match="name">
    <title>
        <xsl:apply-templates select="@*|node()"/>
    </title>
</xsl:template> 
Run Code Online (Sandbox Code Playgroud)

请注意,xsl:element如果您只是输出固定的元素名称,则无需使用.