XML flaten重复节点

时间:2012-09-12 15:45:13

标签: xml xslt

我的项目中有以下XML结构。我需要写一些转换重复节点来制作扁平缝合的东西

<bookstore>
  <book >
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book >
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
  </book>
  <book>
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>39.95</price>
  </book>
</bookstore>

我想像这样展平结构

<bookstore>

    <bookonetitle lang="en">Everyday Italian</bookonetitle>
    <bookoneauthor>Giada De Laurentiis</bookoneauthor>
    <bookoneyear>2005</bookoneyear>
    <bookoneprice>30.00</bookoneprice>


    <booktwotitle lang="en">Harry Potter</booktwotitle>
    <booktwoauthor>J K. Rowling</booktwoauthor>
    <booktwoyear>2005</booktwoyear>
    <booktwoprice>29.99</booktwoprice>

    <bookthreetitle lang="en">Learning XML</bookthreetitle>
    <bookthreetitle>Erik T. Ray</bookthreetitle>
    <bookthreetitle>2003</bookthreetitle>
    <bookthreetitle>39.95</bookthreetitle>



</bookstore>

2 个答案:

答案 0 :(得分:3)

你的输出结构让我觉得非常尴尬。你可能想重新考虑一下。但无论如何,这个XSLT 1.0样式表......

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

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

<xsl:template match="book">
  <xsl:apply-templates select="node()"/>
</xsl:template>

<xsl:template match="book/*">
  <xsl:element name="book-{count(../preceding-sibling::book)+1}-{local-name()}">
    <xsl:apply-templates select="@*|node()"/>
  </xsl:element>
</xsl:template>

</xsl:stylesheet>

...会将您的样本输入转换为...

<bookstore>
  <book-1-title lang="en">Everyday Italian</book-1-title>
  <book-1-author>Giada De Laurentiis</book-1-author>
  <book-1-year>2005</book-1-year>
  <book-1-price>30.00</book-1-price>
  <book-2-title lang="en">Harry Potter</book-2-title>
  <book-2-author>J K. Rowling</book-2-author>
  <book-2-year>2005</book-2-year>
  <book-2-price>29.99</book-2-price>
  <book-3-title lang="en">Learning XML</book-3-title>
  <book-3-author>Erik T. Ray</book-3-author>
  <book-3-year>2003</book-3-year>
  <book-3-price>39.95</book-3-price>
</bookstore> 

答案 1 :(得分:1)

根据Michael Kay的评论,您最好的选择是使用XSLT 2.0指令:

<xsl:number value="$n" format="w"/>

但是,如果你不能使用XSLT 2.0并且书籍数量有限且提前知道了限制,那么可以使用这样的解决方案:

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

 <my:numbers>
   <num>one</num>
   <num>two</num>
   <num>three</num>
   <num>four</num>
   <num>five</num>
   <num>six</num>
   <num>seven</num>
   <num>eight</num>
   <num>nine</num>
   <num>ten</num>
   <num>eleven</num>
   <num>twelve</num>
 </my:numbers>

 <xsl:variable name="vNumbers" select="document('')/*/my:numbers/*"/>

 <xsl:template match="/*">
  <bookstore><xsl:apply-templates/></bookstore>
 </xsl:template>
 <xsl:template match="book">
  <xsl:apply-templates select="*">
   <xsl:with-param name="pPos" select="position()"/>
  </xsl:apply-templates>
  <xsl:text>&#xA;</xsl:text>
 </xsl:template>

 <xsl:template match="book/*">
   <xsl:param name="pPos"/>

   <xsl:element name="book{$vNumbers[$pPos]}{name()}">
     <xsl:copy-of select="@*|node()"/>
   </xsl:element>
 </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用此转换时

<bookstore>
  <book >
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book >
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
  </book>
  <book>
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>39.95</price>
  </book>
</bookstore>

产生了想要的正确结果

<bookstore>
   <bookonetitle lang="en">Everyday Italian</bookonetitle>
   <bookoneauthor>Giada De Laurentiis</bookoneauthor>
   <bookoneyear>2005</bookoneyear>
   <bookoneprice>30.00</bookoneprice>

   <booktwotitle lang="en">Harry Potter</booktwotitle>
   <booktwoauthor>J K. Rowling</booktwoauthor>
   <booktwoyear>2005</booktwoyear>
   <booktwoprice>29.99</booktwoprice>

   <bookthreetitle lang="en">Learning XML</bookthreetitle>
   <bookthreeauthor>Erik T. Ray</bookthreeauthor>
   <bookthreeyear>2003</bookthreeyear>
   <bookthreeprice>39.95</bookthreeprice>

</bookstore>
相关问题