Объединение по взаимосвязанным атрибутам - PullRequest
0 голосов
/ 21 января 2020

Необходимо объединить 3-х уровневые дочерние и родительские отношения двумя параллельными способами.

1 - Выход с конкатенацией полных уровней

2 - Выход с делением по уровню

исходный код

<A>
  <X id="top"                        text="first"  text2="*"/>
  <X id="middle" id-parent="top"     text="second" text2="**"/>
  <X id="bottom" id-parent='middle"' text="third"  text2="***"/>
</A>

Текущий XSLT-код частично решает второй вариант. Он делится в соответствии с уровнем, но вычисление постфикса уровня не привязано к вычислениям иерархии. Нижний (нижний) уровень не отображается. Также порядок выходных уровней обратен желаемому.

xslt преобразование

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

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

      <xsl:key name="ref" match="X" use="@id"/>
      <xsl:template match="X">
        <xsl:copy>
          <xsl:copy-of select="@*"/>
          <xsl:apply-templates select="key('ref', @id-parent)" mode="att"/>
        </xsl:copy>
      </xsl:template>

      <xsl:template match="X" mode="att">
        <xsl:param name="pos" select="count(@*) + 1"/>
        <xsl:attribute name="level-{$pos}">
          <xsl:value-of select="concat(@text,' ', '| ', @text2)"/>
        </xsl:attribute>
        <xsl:apply-templates select="key('ref', @id-parent)" mode="att">
          <xsl:with-param name="pos" select="$pos + 1"/>
        </xsl:apply-templates>
      </xsl:template>

    </xsl:stylesheet>

взаимосвязь схема

https://xsltfiddle.liberty-development.net/bFWRAoS/1

желаемый выход

<A>   <!-- KIND OF-->
  <X id="top"                        text="first"  text2="*"   chain-text="first *"                         level-1="first | *" /> <!-- however, this upper level may remain as in the base source and don't be changed -->
  <X id="middle"  id-parent="top"    text="second" text2="**"  chain-text="first * | second **"             level-1="first | *" level-2="second | **"/>
  <X id="bottom"  id-parent="middle" text="third"  text2="**"  chain-text="first * | second ** | third ***" level-1="first | *" level-2="second | **" level-3="third | ***"/>
</A>

1 Ответ

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

Попробуйте это

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

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

    <xsl:key name="ref" match="X" use="@id"/>

    <xsl:template match="X">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:variable name="Xs">
            <xsl:call-template name="XATT">
                <xsl:with-param name="currentX" select="."/>
                <xsl:with-param name="X" select=".">
                </xsl:with-param>
            </xsl:call-template>
            </xsl:variable>
            <xsl:if test="$Xs[node()]">
                <xsl:attribute name="chain-text">
                    <xsl:for-each select="$Xs/X">
                        <xsl:if test="position() ne 1"><xsl:text> | </xsl:text></xsl:if>
                        <xsl:value-of select="concat(@text, ' ', @text2)"/>
                    </xsl:for-each>
                </xsl:attribute>
                <xsl:for-each select="$Xs/X">
                    <xsl:attribute name="level-{position()}"><xsl:value-of select="concat(@text, ' | ', @text2)"/></xsl:attribute>
                </xsl:for-each>
            </xsl:if>

        </xsl:copy>
    </xsl:template>

    <xsl:template name="XATT">
        <xsl:param name="currentX"/>
        <xsl:param name="X"/>
        <xsl:choose>
            <xsl:when test="$currentX/@id-parent">
                <xsl:call-template name="XATT">
                    <xsl:with-param name="currentX" select="key('ref', $currentX/@id-parent)"/>
                    <xsl:with-param name="X">
                        <xsl:copy-of select="key('ref', $currentX/@id-parent)"/>
                        <xsl:copy-of select="$X"/>
                    </xsl:with-param>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy-of select="$X"/>
            </xsl:otherwise>
        </xsl:choose>

    </xsl:template>

</xsl:stylesheet>

См. Преобразование в https://xsltfiddle.liberty-development.net/bFWRAoS/2

...