重新格式化XML以获得单独的数据集(有条件地打开/关闭标记?)

时间:2013-02-27 14:10:12

标签: xml xslt

我(遗憾的是)必须使用的软件会生成包含多个数据集的XML文件(请参阅以下示例:“文档1”,“文档2”,...)但不用包装{{1 }} 标签。它看起来像这样:

<document>

正如您所看到的,每个新的“文档”都在其第一个<print> <section> <col1>*****</col1> <col2>Document 1</col2> </section> <section> <col1>Title</col1> <col2>Title 1</col2> </section> <section> <col1>Year</col1> <col2>2011</col2> </section> <section /> <section> <col1>*****</col1> <col2>Document 2</col2> </section> <section> <col1>Title</col1> <col2>Title 2</col2> </section> <section> <col1>Year</col1> <col2>2012</col2> </section> <section /> <section> <col1>*****</col1> <col2>Document 3</col2> </section> <section> <col1>Title</col1> <col2>Title 3</col2> </section> <section> <col1>Year</col1> <col2>2013</col2> </section> <section /> ... </print> 标记中以<col1>*****</col1>开头,并以(或更具体:后跟)空<section></section>结尾标签

我想要做的是取出每个<section />值并将其放入包装标签,最后我应该得到文档的分离数据集。结果应如下所示:

<col2>

所以我必须获取所有<print> <document> <docno>Document 1</docno> <title>Title 1</title> <year>2011</year> </document> <document> <docno>Document 2</docno> <title>Title 2</title> <year>2012</year> </document> <document> <docno>Document 3</docno> <title>Title 3</title> <year>2013</year> </document> </print> 值,将它们放入新元素并将它们包装在<col2>标记中。我尝试使用以下XSLT并且我获得了部分成功(我可以获得<document>值),但是在<col2>标记内(我尝试包装<xsl:when>值)它会抛出错误,因为<col2>标记未立即关闭:

<document>

我发现在XSLT中,有条件地打开和关闭标签是不可能的,但我确信还有另一种解决方案如何实现我的目标......我只是没有太多经验才能找到它。有人能指出我正确的方向吗?非常感谢你提前!

2 个答案:

答案 0 :(得分:1)

如果您可以使用XSLT 2.0,还有更优雅的方法,但如果您知道每个空<section>元素之间有三个<section/>个元素,那么您可以做一些简单的事情这(XSLT 1.0兼容):

样式表

<?xml version="1.0"?>

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

  <xsl:template match="print">
    <xsl:copy>
      <!--
      Only apply the first <section> child of <print> and those <section> children
      whose first preceding <section> sibling is an empty <section/> element
      -->
      <xsl:apply-templates select="section[position() = 1
        or preceding-sibling::section[1][not(node())]]"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="section">
    <document>
      <!--
      Transform the <col2> child of this <section> into a <docno> elemen
      -->
      <xsl:apply-templates select="col2" mode="number"/>
      <!--
      Transform the <col2> element of the first following <section> sibling into
      a <title> element
      -->
      <xsl:apply-templates select="following-sibling::section[1]/col2" mode="title"/>
      <xsl:apply-templates select="following-sibling::section[2]/col2" mode="year"/>
    </document>
  </xsl:template>

  <xsl:template match="col2" mode="number">
    <docno>
      <xsl:value-of select="."/>
    </docno>
  </xsl:template>

  <xsl:template match="col2" mode="title">
    <title>
      <xsl:value-of select="."/>
    </title>
  </xsl:template>

  <xsl:template match="col2" mode="year">
    <year>
      <xsl:value-of select="."/>
    </year>
  </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:1)

使用(在XSLT 2.0中)

<xsl:template match="print">
  <xsl:for-each-group select="section" 
          group-starting-with="section[starts-with(col2, 'Document')]">   
   <document>
     <docno><xsl:value-of select="current-group()[1]/col2"/>
     ... etc ...
   </document>
  </xsl:for-each-group>
</xsl:template>