代码之家  ›  专栏  ›  技术社区  ›  Jay

XSL:计数子节点中以前的唯一兄弟姐妹

  •  1
  • Jay  · 技术社区  · 16 年前


    这是延续 this question 但有点复杂。我认为Muenchian方法是实现这一点的最佳方法,因为这个文件的长度会很大。

    我有以下XML(长度很抱歉)

    <?xml version="1.0" encoding="utf-8" ?>
    <ROLEACTIONINFO>
      <ROLE name="TESTER">
        <ACTIONINFO>
          <PERMINFO>
            <PERM type="PT0" field="ALL" permfrom="PERM1565"/>
          </PERMINFO>
        </ACTIONINFO>
      </ROLE>
      <ROLE name="PARENT1">
        <ACTIONINFO>
        </ACTIONINFO>
      </ROLE>
      <ROLE name="PARENT1">
        <ACTIONINFO>
          <PERMINFO>
            <PERM type="PT8" field="ALL" permfrom="PERM1"/>
          </PERMINFO>
        </ACTIONINFO>
      </ROLE>
      <ROLE name="PARENT1">
        <ACTIONINFO>
          <PERMINFO>
            <PERM type="PT7" field="ALL" permfrom="PERM2"/>
            <PERM type="PT7" field="ALL" permfrom="PERM54"/>
          </PERMINFO>
        </ACTIONINFO>
      </ROLE>
      <ROLE name="PARENT2">
        <ACTIONINFO>
          <PERMINFO>
            <PERM type="PT6" field="ALL" permfrom="PERM1"/>
          </PERMINFO>
        </ACTIONINFO>
      </ROLE>
      <ROLE name="PARENT2">
        <ACTIONINFO>
          <PERMINFO>
            <PERM type="PT5" field="ALL" permfrom="PERM2"/>
          </PERMINFO>
        </ACTIONINFO>
      </ROLE>
      <ROLE name="PARENT3">
        <ACTIONINFO>
          <PERMINFO>
            <PERM type="PT2" field="ALL" permfrom="PERM44"/>
          </PERMINFO>
        </ACTIONINFO>
      </ROLE>
     </ROLEACTIONINFO>
    

       <xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="text"/>
      <xsl:template match="text()"/>
    
      <xsl:key name="kRole" match="ROLE[ACTIONINFO/PERMINFO/PERM]" use="@name" />
    
      <xsl:template match="PERM">
        <xsl:variable name="roles-so-far" select="ancestor::ROLE | ancestor::ROLE/preceding-sibling::ROLE[ACTIONINFO/PERMINFO/PERM]"/>
        <!-- Only select the first instance of each ROLE name -->
        <xsl:variable name="roles-so-far-unique"              
                       select="$roles-so-far[generate-id(ancestor::ROLE) = generate-id(key('kRole',ancestor::ROLE/@name)[1])]"/>
        <xsl:apply-templates select="ancestor::ROLE/@name"/>
        <xsl:text>&#x9;</xsl:text>
        <xsl:apply-templates select="@permfrom"/>
        <xsl:text>&#x9;</xsl:text>
        <xsl:value-of select="count($roles-so-far-unique)"/>
        <!-- linefeed -->
        <xsl:text>&#xA;</xsl:text>
      </xsl:template>
    
    </xsl:stylesheet>
    

    以下是所需的输出:

    TESTER  PERM1565    1
    PARENT1 PERM1   2
    PARENT1 PERM2   2
    PARENT1 PERM54  2
    PARENT2 PERM1   3
    PARENT2 PERM2   3
    PARENT3 PERM44  4
    

    TESTER  PERM1565    1
    PARENT1 PERM1   2
    PARENT1 PERM2   3
    PARENT1 PERM54  3
    PARENT2 PERM1   4
    PARENT2 PERM2   5
    PARENT3 PERM44  6
    

    1 回复  |  直到 8 年前
        1
  •  1
  •   Tomalak    16 年前

    这来自每一个 <PERM> <ROLE> 并计算其独特的前辈:

    <xsl:stylesheet
      version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    >
    
      <xsl:output method="text" />
    
      <xsl:variable name="TAB" select="'&#x09;'" />
      <xsl:variable name="LF"  select="'&#x0A;'" />
    
      <xsl:key name="kRole" match="ROLE" use="@name" />
    
      <xsl:template match="/">
        <xsl:apply-templates select="//PERM" />
      </xsl:template>
    
      <xsl:template match="PERM">
        <xsl:variable name="vThisRole" select="ancestor::ROLE[1]" />
        <xsl:variable name="vPrecedingRoles" select="
          ($vThisRole | $vThisRole/preceding-sibling::ROLE)
        " />
        <xsl:variable name="vUniquePrecedingRoles" select="
          $vPrecedingRoles[count(. | key('kRole', ./@name)[1]) = 1]
        " />
        <xsl:value-of select="
          concat(
            $vThisRole/@name, $TAB,
            @permfrom, $TAB,
            count($vUniquePrecedingRoles), $LF
          )
        " />
      </xsl:template>
    
    </xsl:stylesheet>
    

    TESTER  PERM1565        1
    PARENT1 PERM1   2
    PARENT1 PERM2   2
    PARENT1 PERM54  2
    PARENT2 PERM1   3
    PARENT2 PERM2   3
    PARENT3 PERM44  4
    

    如果你问我,你正在处理的XML的状态非常糟糕。至少,任何与安全相关的东西都是通过“前面唯一名称的计数”而不是适当的数据结构来表达的,这让我挠头。;-)你能改变一下输入吗?