XSLT:将平面XML转换为分层XML

时间:2018-07-14 14:24:51

标签: xml xslt

我是xml的新手,这对我来说很难理解XSLT的工作原理。 您能帮我解决xslt文件中的一些错误吗? 我想转换此输入文件:

Reward.java

进入:

startActivityForResult()

规则是:

  1. “ nb”节点指示每个父级的子级数。它可以 为0。

  2. 节点“ child1”和“ child2”不同。它们很复杂 与嵌套循环等。我上面的输入文件已简化为演示。
    我     想,我必须使用“复制”指令。

  3. 对我来说困难的是:

    • 对于每个父节点,我必须读取当前父节点之后定义的子节点数(“ nb”)
    • 当“父”值是“ AAA”时,我必须读取“ child1”
      当“父”值是!= AAAA时,我必须读取“ childe2”节点。 / li>

这是我的XSLT文件,结果不完全符合预期:

<?xml version="1.0" encoding="utf-8"?>
<data>
    <parent><string >AAA</string></parent>
    <nb><string >2</string></nb>
    <child1>aaa-1</child1>
    <child1>aaa-2</child1>
    <parent><string >BBB</string></parent>
    <nb><string>1</string></nb>
    <child2>bbb-1</child2>
    <parent><string >CCC</string></parent>
    <nb><string >0</string></nb>
</data>

预先感谢
最诚挚的问候

2 个答案:

答案 0 :(得分:1)

如果数据是一致的,也就是说,如果总是有child1/child2元素指示的nb元素的数量和parent值的要求,那么您可以简单地处理不同的类型的parent元素中

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="3.0">

  <xsl:output indent="yes"/>

  <xsl:template match="data">
      <xsl:copy>
          <xsl:apply-templates select="parent"/>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="parent[string = 'AAA']">
      <xsl:copy>
          <xsl:variable name="n" select="following-sibling::nb[1]"/>
          <xsl:copy-of select="string, following-sibling::nb[1], following-sibling::child1[position() &lt;= $n]"/>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="parent[string != 'AAA']">
      <xsl:copy>
          <xsl:variable name="n" select="following-sibling::nb[1]"/>
          <xsl:copy-of select="string, following-sibling::nb[1], following-sibling::child2[position() &lt;= $n]"/>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/94hvTzk/0拥有该示例,您也可以在XSLT 1中作为

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

  <xsl:output indent="yes"/>

  <xsl:template match="data">
      <xsl:copy>
          <xsl:apply-templates select="parent"/>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="parent[string = 'AAA']">
      <xsl:copy>
          <xsl:variable name="n" select="following-sibling::nb[1]"/>
          <xsl:copy-of select="string | following-sibling::nb[1] | following-sibling::child1[position() &lt;= $n]"/>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="parent[string != 'AAA']">
      <xsl:copy>
          <xsl:variable name="n" select="following-sibling::nb[1]"/>
          <xsl:copy-of select="string | following-sibling::nb[1] | following-sibling::child2[position() &lt;= $n]"/>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

在线https://xsltfiddle.liberty-development.net/94hvTzk/1

如果数据不一致,那么至少在XSLT 2或3中,for-each-group select="*" group-starting-with="parent"data元素的上下文中将很容易识别相邻的元素并创建parent包装结果。

答案 1 :(得分:1)

使用XSLT 3.0,这很简单

<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="data">
    <data>
      <xsl:for-each-group select="*" group-starting-with="parent">
        <parent>
          <xsl:copy-of select="*, tail(current-group())"/>
        </parent>
      </xsl:for-each-group>
    </data>
  </xsl:template>
</xsl:transform>