Как перебирать узлы и пропускать повторяющиеся узлы с одинаковым значением - XSLT 1,0 - PullRequest
0 голосов
/ 11 апреля 2019

У меня есть xml-подобие,

        <DESIGN-FUNCTION-PROTOTYPE>
          <SHORT-NAME>xxx</SHORT-NAME>
          <TYPE-TREF TYPE="DESIGN-FUNCTION-PROTOTYPE">ABC/DEF/123</TYPE-TREF>
        </DESIGN-FUNCTION-PROTOTYPE>
        <DESIGN-FUNCTION-PROTOTYPE>
          <SHORT-NAME>yyy</SHORT-NAME>
          <TYPE-TREF TYPE="DESIGN-FUNCTION-PROTOTYPE">LMN/OPQ/123</TYPE-TREF>
        </DESIGN-FUNCTION-PROTOTYPE>
        <DESIGN-FUNCTION-PROTOTYPE>
          <SHORT-NAME>mmm</SHORT-NAME>
          <TYPE-TREF TYPE="DESIGN-FUNCTION-PROTOTYPE">XYZ/GHY/456</TYPE-TREF>
        </DESIGN-FUNCTION-PROTOTYPE>
        <DESIGN-FUNCTION-PROTOTYPE>
          <SHORT-NAME>nnn</SHORT-NAME>
          <TYPE-TREF TYPE="DESIGN-FUNCTION-PROTOTYPE">AJK/UTL/456</TYPE-TREF>
        </DESIGN-FUNCTION-PROTOTYPE>

Мой xslt,

    <xsl:template name="substring-after-last">
    <xsl:param name="string" />
    <xsl:param name="delimiter" />
    <xsl:choose>
      <xsl:when test="contains($string, $delimiter)">
        <xsl:call-template name="substring-after-last">
          <xsl:with-param name="string"
            select="substring-after($string, $delimiter)" />
          <xsl:with-param name="delimiter" select="$delimiter" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
          <xsl:value-of select="$string" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

<xsl:for-each select="select="//DESIGN-FUNCTION-PROTOTYPE/ea:TYPE-TREF[@TYPE='DESIGN-FUNCTION-TYPE']">
      <xsl:variable name="myVar" select="current()"/>
      <xsl:variable name="taskName" select="../ea:SHORT-NAME"/>

         <xsl:variable name="Var7">    
         <xsl:call-template name="substring-after-last">
         <xsl:with-param name="string" select="$myVar" />
         <xsl:with-param name="delimiter" select="'/'" />
         </xsl:call-template>
         </xsl:variable>

         <varoutput> 
         <xsl:value-of select="$Var7"/>
         </varoutput>

</xsl:for-each>

Я собираюсь перебрать все элементы 'DESIGN-FUNCTION-PROTOTYPE' и отобразить суб-строка значения 'TYPE-TREF', но если подстрока значения 'TYPE-TREF' уже прочитана .. я должен пропустить этот элемент.

Ожидаемый вывод,

123
456

А не,

123
123
456
456

В общем, я должен рассмотреть только первое вхождение и пропустить остальные.

1 Ответ

2 голосов
/ 11 апреля 2019

Этого можно добиться, используя метод Muenchian Grouping , метод группировки для XSLT-1.0.
В следующем примере кода он реализуется для сортировки дублетов:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" omit-xml-declaration="yes" />
    <xsl:key name="proto" match="DESIGN-FUNCTION-PROTOTYPE" use="TYPE-TREF" />

    <xsl:template match="/">
        <xsl:for-each select="//DESIGN-FUNCTION-PROTOTYPE[generate-id() = generate-id(key('proto',TYPE-TREF)[1])]">
            <varoutput> 
                <xsl:value-of select="TYPE-TREF"/>
            </varoutput>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

Его вывод:

<varoutput>ABC</varoutput>
<varoutput>XYZ</varoutput>

Ответ на ваш теперь другой вопрос, реализующий ту же технику, может быть

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" omit-xml-declaration="yes" />
    <xsl:key name="proto" match="DESIGN-FUNCTION-PROTOTYPE" use="substring-after(substring-after(TYPE-TREF,'/'),'/')" />

    <xsl:template match="/">
        <xsl:for-each select="//DESIGN-FUNCTION-PROTOTYPE[generate-id() = generate-id(key('proto',substring-after(substring-after(TYPE-TREF,'/'),'/'))[1])]">
            <xsl:value-of select="substring-after(substring-after(TYPE-TREF,'/'),'/')"/><xsl:text>&#xA;</xsl:text>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

Его вывод:

123
456

Обратите внимание, что существенное изменение вопроса после подходящего ответа осуждается правилами SO.Не делайте этого снова.

...