XML转换-如果发生最大次数,将childNode移到另一个parentNode

时间:2019-05-22 13:59:39

标签: xml xslt

我正在使用Java(通过.xsl)进行XML-XML转换。目前,我很难限制一个节点的最大出现次数,并将其余的转移到另一个parentNode。

例如: 我有一个如下的XML

<room>
    <box>
        <ball>1</ball>
        <ball>2</ball>
        <ball>3</ball>
        <ball>4</ball>
        <ball>5</ball>
        <ball>6</ball>
        <ball>7</ball>
    </box>
</room>

然后,我需要转换为仅允许每个“ box”元素最多出现3次的XML。如果超过3,则将创建“ box”的新parentNode,然后将下3个“ ball”元素放入其中。

我期望的XML转换输出如下:

<room>
    <box>
        <ball>1</ball>
        <ball>2</ball>
        <ball>3</ball>
    </box>
    <box>
        <ball>4</ball>
        <ball>5</ball>
        <ball>6</ball>
    </box>
    <box>
        <ball>7</ball>
    </box>
</room>

如果有人可以指导我如何为该规则创建XSL样式表,我将不胜感激。

2 个答案:

答案 0 :(得分:2)

一个简单的XSLT-1.0解决方案使用以下模板:

<xsl:template match="/room">
    <xsl:copy>
        <xsl:apply-templates select="box/ball[position() mod 3 = 1]" />
    </xsl:copy>
</xsl:template>

<xsl:template match="ball">
    <box>
        <xsl:copy-of select="." />
        <xsl:copy-of select="following-sibling::ball[1]" />
        <xsl:copy-of select="following-sibling::ball[2]" />
    </box>
</xsl:template>

答案 1 :(得分:1)

在XSLT 2/3中,这可以通过位置分组<xsl:for-each-group select="ball" group-adjacent="(position() - 1) idiv $size">来解决,例如使用XSLT 3:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:param name="size" as="xs:integer" select="3"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="box">
      <xsl:for-each-group select="ball" group-adjacent="(position() - 1) idiv $size">
          <xsl:copy select="..">
              <xsl:apply-templates select="current-group()"/>
          </xsl:copy>
      </xsl:for-each-group>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/3NJ38ZA