开发者

XSL unique values per node

开发者 https://www.devze.com 2022-12-28 21:26 出处:网络
ok i have this xml <roots> <root> <name>first</name> <item type=\'test\'><something>A</something></item>

ok i have this xml

<roots>
<root>
    <name>first</name>
    <item type='test'><something>A</something></item>
    <item type='test'><something>B</something></item>
    <item type='test'><something>C</something></item>
    <item type='test'><something>A</something></item>
    <item type='other'><something>A</something></item>
    <item type='test'><something>B</something></item>
    <item type='other'><something>D</something></item>

</root>
<root>
<name>second</name>
    <item type='test'><something>E</something></item>
    <item type='test'><something>B</something></item>
    <item type='test'><something>F</something&g开发者_运维百科t;</item>
    <item type='test'><something>A</something></item>
    <item type='other'><something>A</something></item>
    <item type='test'><something>B</something></item>
    <item type='other'><something>D</something></item>

</root>

</roots>

now i need to get the unique values of each root node so far i have

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output indent="yes" method="text"/>
  <xsl:key name="item-by-value" match="something" use="."/>
  <xsl:key name="rootkey" match="root" use="name"/>

  <xsl:template match="/">
    <xsl:for-each select="key('rootkey','second')">
      <xsl:for-each select="item/something">
        <xsl:if test="generate-id() = generate-id(key('item-by-value', normalize-space(.)))">
          <xsl:value-of select="."/>
        </xsl:if>
      </xsl:for-each> 
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

if i use "First" as the key to get only the first root i get a good result ABCD

how ever if i use "second" i only get EF but i need the result to be ABDFE


I get EBFAD with a slight modification of your xsl. The key is that if you're using the key to find the first node with this content under the given root element, then the key needs to be specific to the root element. I changed the xsl:key to:

<xsl:key name="item-by-value" match="something"
 use="concat(normalize-space(.), ' ', generate-id(./ancestor::root))"/>

Then the xsl:if test becomes:

<xsl:if test="generate-id() = generate-id(key('item-by-value', 
                  concat(normalize-space(.), ' ', generate-id(./ancestor::root))))">


This is a case where you must use a compound key.

This transformation:

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

 <xsl:key name="kSomethingByNameAndVal" match="something"
  use="concat(../../name, '+', .)"/>

 <xsl:template match="/">
   <xsl:for-each select="*/*">
     <xsl:for-each select=
      "item/something
             [generate-id()
             =
              generate-id(key('kSomethingByNameAndVal',
                               concat(../../name, '+', .)
                              )
                          )
             ]
      ">

       <xsl:value-of select="."/>
     </xsl:for-each>
     <xsl:text>&#xA;</xsl:text>
   </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document correctly produces the wanted result:

ABCD

EBFAD


I think you're pretty close. But you only want the first value of the item-by-value key which has the correct root as parent:

<xsl:for-each select="key('rootkey','second')">
    <xsl:variable name="root" select="generate-id()" />
    <xsl:for-each select="item/something">
        <xsl:sort order="ascending" select="." data-type="text"/>
        <xsl:if test="generate-id() = generate-id(key('item-by-value', .)[generate-id(ancestor::root)=$root][1])">
            <xsl:value-of select="."/>
        </xsl:if>
    </xsl:for-each>
</xsl:for-each>
0

精彩评论

暂无评论...
验证码 换一张
取 消