在更改某些属性时复制整个XML文件

时间:2014-03-09 18:20:16

标签: xml xslt

这是XML文件:

<libros>
  <libro>
    <titulo>El Hobbit</titulo>
    <autor>J. R. Tolkien</autor>
  </libro>
  <libro>
    <titulo>La colmena</titulo>
    <autor>C. J. Cela</autor>
  </libro>
  <libro>
    <titulo>Guerra y Paz</titulo>
    <autor>León Tolstoi</autor>
  </libro>
</libros>

XSL必须做的是:取标签“autor”并将其作为属性放在“libro”中,如下所示:

<libro autor="León Tolstoi">
   <titulo>Guerra y Paz</titulo>
</libro>

据我所知,这是:

<xsl:template match="libros">
 <xsl:copy>
        <xsl:element name="libro">
            <xsl:attribute name="autor">
                <xsl:value-of select="//libro[1]/autor/text()"/>
            </xsl:attribute>
            <xsl:value-of select="//libro[1]/titulo/text()"/>
        </xsl:element>
        <xsl:element name="libro">
            <xsl:attribute name="autor">
                <xsl:value-of select="//libro[2]/autor/text()"/>
            </xsl:attribute>
            <xsl:value-of select="//libro[2]/titulo/text()"/>
        </xsl:element>
        <xsl:element name="libro">
            <xsl:attribute name="autor">
                <xsl:value-of select="//libro[3]/autor/text()"/>
            </xsl:attribute>
            <xsl:value-of select="//libro[3]/titulo/text()"/>
        </xsl:element>
    </xsl:copy>
</xsl:template>

输出必须如此,但是我看到了这个问题,当我有很多“libro”元素时会发生什么?谷歌周围我发现这是复制整个文档,但我没有找到正确的方法来编辑它以满足我的需求:

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

2 个答案:

答案 0 :(得分:4)

您使用身份模板走在正确的轨道上 - 这确实会将整个输入文档按原样复制到输出中,但是这样做而不是使用单个<xsl:copy-of select="/"/>这样做是您可以覆盖要以不同方式处理的特定节点的标识模板。您不会“编辑”身份模板本身,而是为特殊情况添加其他模板。在你的情况下,你需要

  • autor元素和
  • 添加额外的libro属性
  • 完全禁止autor 元素

对于第一个,你需要一个像

这样的模板
<xsl:template match="libro">
  <!-- {} is an "attribute value template" - an XPath expression rather than a
       literal string -->
  <libro autor="{autor}">
    <!-- continue processing all children as normal -->
    <xsl:apply-templates select="@*|node()" />
  </libro>
</xsl:template>

并且对于第二个,您需要一个空的“无所事事”模板 - 当您遇到autor元素时,将其替换为无

<xsl:template match="autor" />

以下是完整的样式表:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="libro">
    <libro autor="{autor}">
      <xsl:apply-templates select="@*|node()" />
    </libro>
  </xsl:template>

  <xsl:template match="autor" />

</xsl:stylesheet>

答案 1 :(得分:2)

你应该寻找这个:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="libro">
    <xsl:copy>
        <xsl:attribute name="autor">
            <xsl:value-of select="autor"/>
        </xsl:attribute>
        <xsl:copy-of select="titulo"/>
    </xsl:copy>
</xsl:template>

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