хорошо у меня есть этот 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></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>
теперь я должен получить уникальные значения каждого корневого узла до сих пор, я имею
<?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>
если я использую "Сначала" в качестве ключа для получения только первого корня, я получаю хороший результат ABCD
как когда-либо, если я использую "второй", я только получаю EF, но мне нужен результат, чтобы быть ABDFE
Я получаю EBFAD
с небольшой модификацией вашего файла xsl. Ключ в том, что если вы используете ключ для поиска первого узла с этим содержимым под заданным корневым элементом , тогда ключ должен быть специфическим для корневого элемента. Я изменил xsl: key
на:
<xsl:key name="item-by-value" match="something"
use="concat(normalize-space(.), ' ', generate-id(./ancestor::root))"/>
Тогда тест xsl: if
станет:
<xsl:if test="generate-id() = generate-id(key('item-by-value',
concat(normalize-space(.), ' ', generate-id(./ancestor::root))))">
Думаю, вы довольно близки. Но вам нужно только первое значение ключа по каждому значению, которое имеет правильный корень в качестве родителя:
<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>
Это случай, когда вы должны использовать составной ключ.
Это преобразование :
<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>
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
при правильном применении к предоставленному XML-документу дает желаемый результат :
ABCD
EBFAD