4

我有一个如下的 XML 文件,我想将它转换成另一个 XML 文件。

<body>
  <outline text="A">
    <outline text="Abelson, Harold" author="Harold Abelson" title="Struktur und Interpretation von Computerprogrammen. Eine Informatik-Einführung" publisher="Springer Verlag" isbn="3540520430" year="1991"/>
    <outline text="Abrahams, Paul W." author="Paul W. Abrahams" title="Tex for the Impatient" publisher="Addison-Wesley Pub Co" isbn="0201513757" year="2000"/>
  </outline>
  <outline text="B">
    <outline text="Bach, Fred" author="Fred Bach" title="UNIX Handbuch zur Programmentwicklung" publisher="Hanser Fachbuchverlag" isbn="3446151036"/>
    <outline text="Bach, Maurice J." author="Maurice J. Bach" title="Design of the UNIX Operating System" publisher="Prentice Hall PTR" isbn="0132017997" year="1986"/>
  </outline>
</body>

这是我要转换为的 XML 格式

<list>
    <books text="A">
        <book>
            <text>Abelson, Harold</text>
            <author>Harold Abelson</author>
            <title>Struktur und Interpretation von Computerprogrammen. Eine
                Informatik-Einführung</title>
            <publisher>Springer Verlag</publisher>
            <isbn>3540520430</isbn>
            <year>1991</year>
        </book>
        <book>
            <text>Abrahams, Paul W.</text>
            <author>Paul W. Abrahams</author>
            <title>Tex for the Impatient</title>
            <publisher>Addison-Wesley Pub Co</publisher>
            <isbn>0201513757</isbn>
            <year>2000</year>
        </book>

    </books>
    <books text="B">
        <book>
            <text>Bach, Fred</text>
            <author>Fred Bach</author>
            <title>UNIX Handbuch zur Programmentwicklung</title>
            <publisher>Hanser Fachbuchverlag</publisher>
            <isbn>3446151036</isbn>
            <year />
        </book>

这是我的代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml"/>
    <xsl:template match="body">
        <list> <xsl:apply-templates select="outline"/> </list>
    </xsl:template>

    <xsl:template match="outline">
    <books text= "{@text}">
        <book><xsl:apply-templates select="outline"/> 
        <text><xsl:value-of select="@text" /></text>
        <author><xsl:value-of select="@author" /></author>
        <title><xsl:value-of select="@title" /></title>
        <publisher><xsl:value-of select="@publisher" /></publisher>
        <isbn><xsl:value-of select="@isbn" /></isbn>
        <year><xsl:value-of select="@year" /></year>
        </book>
    </books>
    </xsl:template>


</xsl:stylesheet>

这是我的代码的输出。

<list>
    <books text="A">
        <book>
            <books text="Abelson, Harold">
                <book>
                    <text>Abelson, Harold</text>
                    <author>Harold Abelson</author>
                    <title>Struktur und Interpretation von Computerprogrammen. Eine
                        Informatik-Einführung</title>
                    <publisher>Springer Verlag</publisher>
                    <isbn>3540520430</isbn>
                    <year>1991</year>
                </book>
            </books>

我的输出中有两个额外的元素

<books text="Abelson, Harold">
                <book>

据我所知,这可能是由这行代码引起的。我尝试了几种不同的方法,但没有奏效

<xsl:template match="outline">
        <books text= "{@text}">

附加问题:如果原始 XML 文件包含标题。如何消除头部和标题。我当前的代码在新的 XML 文件中生成“tmp”。

<opml version="1.0">
  <head>
    <title>tmp</title>
    <expansionState></expansionState>
  </head>
  <body>
      <outline text="A">
      <outline text="Abelson, Harold" author="H
4

3 回答 3

3

您在正确的轨道上,但您需要两个outline模板 - 一个用于 top level outline,一个用于 child outlines

outline用以下三个替换您的模板:

  <xsl:template match="head" />

  <xsl:template match="outline">
    <books text="{@text}">
      <xsl:apply-templates select="outline" />
    </books>
  </xsl:template>

  <xsl:template match="outline/outline">
    <book>
      <text>
        <xsl:value-of select="@text" />
      </text>
      <author>
        <xsl:value-of select="@author" />
      </author>
      <title>
        <xsl:value-of select="@title" />
      </title>
      <publisher>
        <xsl:value-of select="@publisher" />
      </publisher>
      <isbn>
        <xsl:value-of select="@isbn" />
      </isbn>
      <year>
        <xsl:value-of select="@year" />
      </year>
    </book>
  </xsl:template>

如果可以安全地假设源文档的属性名称将匹配输出文档中元素的名称,您可以将第二个模板替换为以下两个更短、更精简的模板:

  <xsl:template match="outline/outline">
    <book>
      <xsl:apply-templates select="@text" />
      <xsl:apply-templates select="@author" />
      <xsl:apply-templates select="@title" />
      <xsl:apply-templates select="@publisher" />
      <xsl:apply-templates select="@isbn" />
      <xsl:apply-templates select="@year" />
    </book>
  </xsl:template>

  <xsl:template match="outline/outline/@*">
    <xsl:element name="{name()}">
       <xsl:value-of select="." />
    </xsl:element>
  </xsl:template>
于 2013-01-23T07:10:53.107 回答
3

这是一个稍微更加面向推送的解决方案,它不太依赖于手动将元素从源 XML 拉到结果 XML 中。特别要注意最后一个模板。

当这个 XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output omit-xml-declaration="yes" indent="yes" />
  <xsl:strip-space elements="*" />

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

  <xsl:template match="outline[outline]">
    <books text="{@text}">
      <xsl:apply-templates />
    </books>
  </xsl:template>

  <xsl:template match="outline[not(*)]">
    <book>
      <xsl:apply-templates select="@*" />
    </book>
  </xsl:template>

  <xsl:template match="outline[not(*)]/@*">
    <xsl:element name="{name()}">
      <xsl:value-of select="." />
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

...应用于提供的源 XML:

<body>
  <outline text="A">
    <outline text="Abelson, Harold" author="Harold Abelson" title="Struktur und Interpretation von Computerprogrammen. Eine Informatik-Einführung" publisher="Springer Verlag" isbn="3540520430" year="1991"/>
    <outline text="Abrahams, Paul W." author="Paul W. Abrahams" title="Tex for the Impatient" publisher="Addison-Wesley Pub Co" isbn="0201513757" year="2000"/>
  </outline>
  <outline text="B">
    <outline text="Bach, Fred" author="Fred Bach" title="UNIX Handbuch zur Programmentwicklung" publisher="Hanser Fachbuchverlag" isbn="3446151036"/>
    <outline text="Bach, Maurice J." author="Maurice J. Bach" title="Design of the UNIX Operating System" publisher="Prentice Hall PTR" isbn="0132017997" year="1986"/>
  </outline>
</body>

...产生了想要的结果:

<list>
  <books text="A">
    <book>
      <text>Abelson, Harold</text>
      <author>Harold Abelson</author>
      <title>Struktur und Interpretation von Computerprogrammen.
        Eine Informatik-Einführung</title>
      <publisher>Springer Verlag</publisher>
      <isbn>3540520430</isbn>
      <year>1991</year>
    </book>
    <book>
      <text>Abrahams, Paul W.</text>
      <author>Paul W. Abrahams</author>
      <title>Tex for the Impatient</title>
      <publisher>Addison-Wesley Pub Co</publisher>
      <isbn>0201513757</isbn>
      <year>2000</year>
    </book>
  </books>
  <books text="B">
    <book>
      <text>Bach, Fred</text>
      <author>Fred Bach</author>
      <title>UNIX Handbuch zur Programmentwicklung</title>
      <publisher>Hanser Fachbuchverlag</publisher>
      <isbn>3446151036</isbn>
    </book>
    <book>
      <text>Bach, Maurice J.</text>
      <author>Maurice J. Bach</author>
      <title>Design of the UNIX Operating System</title>
      <publisher>Prentice Hall PTR</publisher>
      <isbn>0132017997</isbn>
      <year>1986</year>
    </book>
  </books>
</list>
于 2013-01-23T08:55:34.617 回答
3

一个更短、更完整的解决方案:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="outline">
    <books text="{@text}">
      <xsl:apply-templates/>
    </books>
  </xsl:template>

  <xsl:template match="outline/outline">
    <book><xsl:apply-templates select="@*"/></book>
  </xsl:template>

  <xsl:template match="outline/outline/@*">
      <xsl:element name="{name()}">
        <xsl:value-of select="." />
      </xsl:element>
  </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<body>
  <outline text="A">
    <outline text="Abelson, Harold" author="Harold Abelson" title="Struktur und Interpretation von Computerprogrammen. Eine Informatik-Einführung" publisher="Springer Verlag" isbn="3540520430" year="1991"/>
    <outline text="Abrahams, Paul W." author="Paul W. Abrahams" title="Tex for the Impatient" publisher="Addison-Wesley Pub Co" isbn="0201513757" year="2000"/>
  </outline>
  <outline text="B">
    <outline text="Bach, Fred" author="Fred Bach" title="UNIX Handbuch zur Programmentwicklung" publisher="Hanser Fachbuchverlag" isbn="3446151036"/>
    <outline text="Bach, Maurice J." author="Maurice J. Bach" title="Design of the UNIX Operating System" publisher="Prentice Hall PTR" isbn="0132017997" year="1986"/>
  </outline>
</body>

产生了想要的正确结果:

<list>
 <books text="A">
   <book>
      <text>Abelson, Harold</text>
      <author>Harold Abelson</author>
      <title>Struktur und Interpretation von Computerprogrammen. Eine Informatik-Einführung</title>
      <publisher>Springer Verlag</publisher>
      <isbn>3540520430</isbn>
      <year>1991</year>
   </book>
   <book>
      <text>Abrahams, Paul W.</text>
      <author>Paul W. Abrahams</author>
      <title>Tex for the Impatient</title>
      <publisher>Addison-Wesley Pub Co</publisher>
      <isbn>0201513757</isbn>
      <year>2000</year>
   </book>
 </books>
 <books text="B">
   <book>
      <text>Bach, Fred</text>
      <author>Fred Bach</author>
      <title>UNIX Handbuch zur Programmentwicklung</title>
      <publisher>Hanser Fachbuchverlag</publisher>
      <isbn>3446151036</isbn>
   </book>
   <book>
      <text>Bach, Maurice J.</text>
      <author>Maurice J. Bach</author>
      <title>Design of the UNIX Operating System</title>
      <publisher>Prentice Hall PTR</publisher>
      <isbn>0132017997</isbn>
      <year>1986</year>
   </book>
 </books>
<list>

说明

  1. 正确使用模板和匹配模式。

  2. 正确使用<xsl:element>


二、如果需要生成元素的特定顺序(因为无法保证源属性的顺序),请使用以下轻微修改

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="outline">
    <books text="{@text}">
      <xsl:apply-templates/>
    </books>
  </xsl:template>

  <xsl:template match="outline/outline">
    <book>
      <xsl:apply-templates select="@*">
        <xsl:sort data-type="number" select=
          string-length(substring-before('text|author|title|publisher|isbn|year',name()))"/>
      </xsl:apply-templates></book>
  </xsl:template>

  <xsl:template match="outline/outline/@*">
      <xsl:element name="{name()}">
        <xsl:value-of select="." />
      </xsl:element>
  </xsl:template>
</xsl:stylesheet>
于 2013-01-23T12:58:11.740 回答