XSLT: скопировать группу узлов с инкрементными значениями - PullRequest
0 голосов
/ 25 января 2020

У меня есть XML, который выглядит следующим образом:

<request>
    <MaterialOrderItems>
        <Item>
            <LineId>1</LineId>
            <ParentLineId>1</ParentLineId>
        </Item>
        <Item>
            <LineId>2</LineId>
            <ParentLineId>1</ParentLineId>
        </Item>
        <Item>
            <LineId>3</LineId>
            <ParentLineId>1</ParentLineId>
        </Item>
    </MaterialOrderItems>
</request>

Я хочу взять это XML и продублировать эту группу предметов (Предмет [1,2,3]) на несколько копий. , Например, если я хочу 2 копии, мой окончательный xml будет выглядеть так:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<request>
    <MaterialOrderItems>
    <Item>
      <LineId>1</LineId>
      <ParentLineId>1</ParentLineId>
    </Item>
    <Item>
      <LineId>2</LineId>
      <ParentLineId>1</ParentLineId>
    </Item>
    <Item>
      <LineId>3</LineId>
      <ParentLineId>1</ParentLineId>
    </Item>
    <Item>
      <LineId>4</LineId>
      <ParentLineId>4</ParentLineId>
    </Item>
    <Item>
      <LineId>5</LineId>
      <ParentLineId>4</ParentLineId>
    </Item>
    <Item>
      <LineId>6</LineId>
      <ParentLineId>4</ParentLineId>
    </Item>
    </MaterialOrderItems>
</request>

Я придумала этот xslt, чтобы сделать это:

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

<xsl:param name="nmaterials" select="2" />

<xsl:template match="node() | @*">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
</xsl:template>


<xsl:template match="//MaterialOrderItems" name="order">
    <xsl:param name="material_number" select="1" />

    <xsl:copy>
          <Item>
            <LineId><xsl:value-of select="((($material_number - 1) * 3) + 1)"/></LineId>
            <ParentLineId><xsl:value-of select="((($material_number - 1) * 3) + 1)"/></ParentLineId>
          </Item>
          <Item>
            <LineId><xsl:value-of select="((($material_number - 1) * 3) + 2)"/></LineId>
            <ParentLineId><xsl:value-of select="((($material_number - 1) * 3) + 1)"/></ParentLineId>
          </Item>
          <Item>
            <LineId><xsl:value-of select="((($material_number - 1) * 3) + 3)"/></LineId>
            <ParentLineId><xsl:value-of select="((($material_number - 1) * 3) + 1)"/></ParentLineId>
          </Item>
    </xsl:copy>

    <xsl:if test="$material_number &lt; $nmaterials">
        <xsl:apply-templates select=".">
            <xsl:with-param name="material_number" select="$material_number + 1" />
        </xsl:apply-templates>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

, и я получить этот вывод:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<request>
  <MaterialOrderItems>
    <Item>
      <LineId>1</LineId>
      <ParentLineId>1</ParentLineId>
    </Item>
    <Item>
      <LineId>2</LineId>
      <ParentLineId>1</ParentLineId>
    </Item>
    <Item>
      <LineId>3</LineId>
      <ParentLineId>1</ParentLineId>
    </Item>
  </MaterialOrderItems>
  <MaterialOrderItems>
    <Item>
      <LineId>4</LineId>
      <ParentLineId>4</ParentLineId>
    </Item>
    <Item>
      <LineId>5</LineId>
      <ParentLineId>4</ParentLineId>
    </Item>
    <Item>
      <LineId>6</LineId>
      <ParentLineId>4</ParentLineId>
    </Item>
  </MaterialOrderItems>
</request>

У меня есть два вопроса:

  1. Как избавиться от узла MaterialOrderItems, повторяющегося здесь? Я хочу, чтобы он только один раз охватывал все предметы.
  2. Как сделать это лучше, обрабатывая оригинал xml? В настоящее время я жестко кодирую оригинальный xml в своем шаблоне XSL. Должен быть лучший способ сделать это.

Пожалуйста, помогите.

1 Ответ

1 голос
/ 25 января 2020

Попробуйте код ниже

см. Преобразование в https://xsltfiddle.liberty-development.net/3NSTbeS

    <?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="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:param name="nmaterials" select="2"/>

    <xsl:template match="MaterialOrderItems">
        <xsl:param name="material_number" select="1"/>
        <xsl:variable name="countitem" select="count(Item)"/>
        <xsl:copy>
            <xsl:copy-of select="*"/>
            <xsl:if test="$material_number != $nmaterials">
                <xsl:call-template name="Copy">
                    <xsl:with-param name="data" select="."/>
                    <xsl:with-param name="material_number" select="$material_number + 1"/>
                    <xsl:with-param name="countitem" select="$countitem"/>
                </xsl:call-template>
            </xsl:if>
        </xsl:copy>
    </xsl:template>

    <xsl:template name="Copy">
        <xsl:param name="data"/>
        <xsl:param name="material_number"/>
        <xsl:param name="countitem"/>
        <xsl:for-each select="$data/Item">
            <xsl:variable name="position" select="position()"/>
            <xsl:apply-templates select=".">
                <xsl:with-param name="pos" select="$position"/>
                <xsl:with-param name="material_number" select="$material_number"/>
                <xsl:with-param name="countitem" select="$countitem"/>
            </xsl:apply-templates>
        </xsl:for-each>
        <xsl:if test="$material_number != $nmaterials">
            <xsl:call-template name="Copy">
                <xsl:with-param name="data" select="$data"/>
                <xsl:with-param name="material_number" select="$material_number + 1"/>
                <xsl:with-param name="countitem" select="$countitem"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

    <xsl:template match="Item">
        <xsl:param name="pos"/>
        <xsl:param name="material_number"/>
        <xsl:param name="countitem"/>
        <xsl:copy>
            <LineId>
                <xsl:value-of select="((($material_number - 1) * $countitem) + $pos)"/>
            </LineId>
            <ParentLineId>
                <xsl:value-of select="((($material_number - 1) * $countitem) + 1)"/>
            </ParentLineId>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...