Объединение определенных узлов и добавление атрибутов в XSLT из XML - PullRequest
0 голосов
/ 13 мая 2019

Я впервые использую XSL, и у меня сложная задача.

Я хотел бы объединить и добавить определенные узлы из моего XML.

Например:

XML:

<Root>
  <Result>ok</Result>
  <Type>SingleObject</Type>
  <Head>
    <DocumentLines>
      <line0>
        <LineNum>0</LineNum>
        <ItemCode>A1234</ItemCode>
        <Dscription>Article1</Dscription>
        <Quantity>5</Quantity>
      </line0>
      <line1>
        <LineNum>1</LineNum>
        <ItemCode>B4321</ItemCode>
        <Dscription>Article2</Dscription>
        <Quantity>6</Quantity>
      </line1>
      <line2>
        <LineNum>2</LineNum>
        <ItemCode>A789</ItemCode>
        <Dscription>Article3</Dscription>
        <Quantity>8</Quantity>
      </line2>
      <line3>
        <LineNum>3</LineNum>
        <ItemCode>A1234</ItemCode>
        <Dscription>Article1</Dscription>
        <Quantity>5</Quantity>
      </line3>
    </DocumentLines>
  </Head>
</Root>

Исходя из ItemCode, я хотел бы объединить строку 0 и строку 3 и сложить количество вместе следующим образом:

<Document_Lines>
  <row>
    <LineNum>0</LineNum>
    <ItemCode>A1234</ItemCode>
    <Dscription>Article1</Dscription>
    <Quantity>10</Quantity>
  </row>
  <row>
    <LineNum>1</LineNum>
    <ItemCode>B4321</ItemCode>
    <Dscription>Article2</Dscription>
    <Quantity>6</Quantity>
  </row>
  <row>
    <LineNum>2</LineNum>
    <ItemCode>A789</ItemCode>
    <Dscription>Article3</Dscription>
    <Quantity>8</Quantity>
  </row>
</Document_Lines>

Мой XSL выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="/">

        <Document_Lines>
          <xsl:for-each select="/Root/Head/DocumentLines/*">
            <xsl:variable name="index" select="1"/>
            <row>
                <LineNum><xsl:value-of select="LineNum[$index]" /></LineNum>
                <ItemCode>  <xsl:value-of select="ItemCode[$index]" /> </ItemCode>
                <Dscription><xsl:value-of select="Dscription[$index]" /></Dscription>
                <Quantity><xsl:value-of select="Quantity[$index]" /></Quantity>
            </row>
          </xsl:for-each>
        </Document_Lines>

  </xsl:template>
</xsl:stylesheet>

Он получает все строки и показывает их правильно, но я действительно не знаю, как двигаться дальше отсюда.Надеюсь, что кто-то может помочь

1 Ответ

1 голос
/ 13 мая 2019

Для упорядоченного вывода в XSLT-1.0 вы должны применить метод Muenchian Grouping .Существует множество примеров такого подхода к SO.

Применительно к вашей личной ситуации код может выглядеть следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:output method="xml" indent="yes"/>
  <xsl:key name="lines" match="*[starts-with(local-name(),'line')]" use="ItemCode" />

  <xsl:template match="/">
    <Document_Lines>
        <xsl:for-each select="/Root/Head/DocumentLines/*[generate-id()=generate-id(key('lines',ItemCode))]">
            <row>
                <LineNum><xsl:value-of select="LineNum" /></LineNum>
                <ItemCode><xsl:value-of select="ItemCode" /> </ItemCode>
                <Description><xsl:value-of select="Dscription" /></Description>
                <Quantity><xsl:value-of select="sum(key('lines',ItemCode)/Quantity)" /></Quantity>
            </row>
        </xsl:for-each>
    </Document_Lines>
  </xsl:template>

</xsl:stylesheet>

Muenchian Grouping состоит из двухчасти:

  1. xsl:key name="values" ...
  2. generate-id()=key(...)

Обе части вместе позволяют группировать элементы line? так, как вы хотите.
Вывод:

<?xml version="1.0"?>
<Document_Lines>
  <row>
    <LineNum>0</LineNum>
    <ItemCode>A1234</ItemCode>
    <Description>Article1</Description>
    <Quantity>10</Quantity>
  </row>
  <row>
    <LineNum>1</LineNum>
    <ItemCode>B4321</ItemCode>
    <Description>Article2</Description>
    <Quantity>6</Quantity>
  </row>
  <row>
    <LineNum>2</LineNum>
    <ItemCode>A789</ItemCode>
    <Description>Article3</Description>
    <Quantity>8</Quantity>
  </row>
</Document_Lines>

Усовершенствованное решение XSLT-2.0 может быть

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

  <xsl:template match="/">
    <Document_Lines>
        <xsl:for-each-group select="/Root/Head/DocumentLines/*[starts-with(local-name(),'line')]" group-by="ItemCode">
            <row>
                <xsl:copy-of select="LineNum, ItemCode, Dscription" />
                <Quantity><xsl:value-of select="sum(current-group()/Quantity)" /></Quantity>
            </row>
        </xsl:for-each-group>
    </Document_Lines>
  </xsl:template>

</xsl:stylesheet>

Его вывод такой же.

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