代码之家  ›  专栏  ›  技术社区  ›  Alan Birtles

从XSLT子查询中选择不同的值

  •  0
  • Alan Birtles  · 技术社区  · 6 年前

    我有这个XML文档:

    <?xml version="1.0" encoding="UTF-8"?>
    <metadata>
      <properties>
        <property name="prop1" type="type1"/>
        <property name="prop2" type="type2"/>
        <property name="prop3" type="type3"/>
        <property name="prop4" type="type1"/>
      </properties>
      <types>
        <type name="type1" group="group1"/>
        <type name="type2" group="group1"/>
        <type name="type3" group="group2"/>
        <type name="type4" group="group3"/>
      </types>
      <groups>
        <group name="group1" owner="owner1"/>
        <group name="group2" owner="owner2"/>
        <group name="group3" owner="owner3"/>
      </groups>
    </metadata>
    

    我正在使用此XSLT转换它:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:template match="/">
        <xsl:variable name="docRoot" select="/" />
        <xsl:for-each select="distinct-values($docRoot/metadata/properties/property/@type)">
          <xsl:variable name="groupOwner" select="$docRoot/metadata/groups/group[@name=$docRoot/metadata/types/type[@name=current()]/@group]/@owner" />
          <xsl:value-of select="$groupOwner"/><xsl:text>
    </xsl:text>
        </xsl:for-each>
      </xsl:template>
    </xsl:stylesheet>
    

    我要做的是打印出文档中所有属性的唯一组所有者列表。我已成功筛选出重复类型 distinct-values 但看不到如何过滤掉重复的所有者。

    电流输出:

    owner1
    owner1
    owner2
    

    所需输出:

    owner1
    owner2
    

    如果它有助于任何两个组拥有相同的所有者。

    2 回复  |  直到 6 年前
        1
  •  3
  •   Tim C    6 年前

    钥匙可以是你的朋友…

    <xsl:key name="types" match="type" use="@name" />
    <xsl:key name="groups" match="group" use="@name" />
    

    那么你可以这样做,甚至不需要 distinct-values 因为不会以这种方式返回重复的节点:

    <xsl:for-each select="key('groups', key('types', metadata/properties/property/@type)/@group)">
    

    例如,尝试此XSLT

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="text" />
    
      <xsl:key name="types" match="type" use="@name" />
      <xsl:key name="groups" match="group" use="@name" />
    
      <xsl:template match="/">
        <xsl:for-each select="key('groups', key('types', metadata/properties/property/@type)/@group)">
          <xsl:value-of select="concat(@owner, '&#10;')" />
        </xsl:for-each>
      </xsl:template>
    </xsl:stylesheet>
    

    实际上,您可以简化 xsl:for-each 对此:

    <xsl:value-of select="key('groups', key('types', metadata/properties/property/@type)/@group)/@owner" separator="&#10;" />
    
        2
  •  1
  •   Alan Birtles    6 年前

    啊,只是需要更努力一点:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:template match="/">
        <xsl:variable name="docRoot" select="/" />
        <xsl:for-each select="distinct-values($docRoot/metadata/groups/group[@name=$docRoot/metadata/types/type[@name=$docRoot/metadata/properties/property/@type]/@group]/@owner)">
          <xsl:value-of select="current()"/><xsl:text>
    </xsl:text>
        </xsl:for-each>
      </xsl:template>
    </xsl:stylesheet>
    

    尽管如此,还是欢迎任何简化建议!