XSLT-преобразование для каждого - PullRequest
0 голосов
/ 05 сентября 2018

Не могли бы вы помочь мне с преобразованием 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 (к сожалению, он не существует :)).

Спасибо Martin

1 Ответ

0 голосов
/ 05 сентября 2018

Предполагая 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 первого line, чтобы сформировать "группу", а затем обработать все с тем же индексом для заполнения группы:

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

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

  <xsl:template match="file">
      <xsl:apply-templates select="line[1]/entry" mode="group"/>
  </xsl:template>

  <xsl:template match="entry" mode="group">
      <xsl:variable name="index">
          <xsl:number format="A" value="position()"/>
      </xsl:variable>
      <xsl:variable name="pos" select="position()"/>
      <xsl:element name="group{$index}">
          <xsl:apply-templates select="../../line/entry[position() = $pos]"/>
      </xsl:element>     
  </xsl:template>

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

</xsl:stylesheet>

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...