每个XSLT转换

时间:2018-09-05 13:51:58

标签: xml loops xslt foreach

您能帮我进行XLST转换吗?

我的输入XML文件包含:

<?xml version="1.0" encoding="UTF-8"?>
<file>
<line>
    <entry>A1</entry>
    <entry>B1</entry>
    <entry>C1</entry>
    <entry>D1</entry>
</line>
<line>
    <entry>A2</entry>
    <entry>B2</entry>
    <entry>C2</entry>
    <entry>D2</entry>
</line>
<line>
    <entry>A3</entry>
    <entry>B3</entry>
    <entry>C3</entry>
    <entry>D3</entry>
</line>
</file>

我想要的输出是:

 <groupA>
    <observation value="A1" />
    <observation value="A2" />
    <observation value="A3" />
 </groupA>
 <groupB>
    <observation value="B1" />
    <observation value="B2" />
    <observation value="B3" />
  </groupB>
 <groupC>
    <observation value="C1" />
    <observation value="C2" />
    <observation value="C3" />
 </groupC>
 <groupD>
    <observation value="D1" />
    <observation value="D2" />
    <observation value="D3" />
 </groupD>

非常感谢您提供任何建议。

我想按条目的位置对条目进行分组。 可以手动编写“ groupX”行。

我知道如何在每个循环中使用,但是我不知道如何将2个循环相互嵌套以获取所需的输出。希望输入的文件代码和所需的代码清晰可见。

如果您将输入文件想象成一个表,则它基本上是for-each-column的语句(不幸的是,它不存在:))。

谢谢 马丁

1 个答案:

答案 0 :(得分:1)

假设XSLT 2或3是一项位置分组任务,可以使用for-each-group解决:

  <xsl:template match="file">
      <xsl:variable name="size" as="xs:integer" select="count(line[1]/entry)"/>
      <xsl:for-each-group select="line/entry" group-by="position() mod $size">
          <xsl:variable name="index" as="xs:string">
              <xsl:number format="A" value="position()"/>
          </xsl:variable>
          <xsl:element name="group{$index}">
              <xsl:apply-templates select="current-group()"/>
          </xsl:element>
      </xsl:for-each-group>
  </xsl:template>

完整的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:mode on-no-match="shallow-copy"/>

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

  <xsl:template match="file">
      <xsl:variable name="size" as="xs:integer" select="count(line[1]/entry)"/>
      <xsl:for-each-group select="line/entry" group-by="position() mod $size">
          <xsl:variable name="index" as="xs:string">
              <xsl:number format="A" value="position()"/>
          </xsl:variable>
          <xsl:element name="group{$index}">
              <xsl:apply-templates select="current-group()"/>
          </xsl:element>
      </xsl:for-each-group>
  </xsl:template>

  <xsl:template match="entry">
      <observation value="{.}"/>
  </xsl:template>

</xsl:stylesheet>

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

您还可以在XSLT 1或更高版本中通过处理第一个entry的{​​{1}}元素来形成一个“组”,然后使用相同的索引处理所有这些以填充该组: / p>

line

https://xsltfiddle.liberty-development.net/bFDb2CF/2