znalazłem ta strona opisując metodę Muenchian, ale myślę, że źle ją stosuję.
Załóżmy, że zwróci to zestaw wieków:
/doc/class/person/descriptive[(@name="age")]/value
1..2..2..2..3..3..4..7
Ale chciałbym, aby węzeł składał się tylko z jednego węzła dla każdego wieku.
1..2..3..4..7
Każda z nich wydaje się zwracać wszystkie wartości zamiast unikalnych wartości:
/doc/class/person/descriptive[(@name="age")][not(value=preceding-sibling::value)]/value
/doc/class/person/descriptive[(@name="age")]/value[not(value=preceding-sibling::value)]
czego mi brakuje?
Odpowiedzi:
22 dla odpowiedzi nr 1Oto przykład:
<root>
<item type="test">A</item>
<item type="test">B</item>
<item type="test">C</item>
<item type="test">A</item>
<item type="other">A</item>
<item type="test">B</item>
<item type="other">D</item>
<item type="">A</item>
</root>
I XPath:
//preceding::item/preceding::item[not(.=preceding-sibling::item)]/text()
Wyniki: A B C D
EDYTOWAĆ: Jak mousio skomentował to nie przechwytuje ostatniego elementu na liście, jeśli jest to jedyny czas, w którym się pojawia. Biorąc pod uwagę to i uwagę Fëanora, oto lepsze rozwiązanie:
/root/item[not(.=preceding-sibling::item)]
14 dla odpowiedzi № 2
Oto mulczańska wersja odpowiedzi BQ na podstawie jego danych:
<?xml version="1.0"?>
<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="item" use="."/>
<xsl:template match="/">
<xsl:apply-templates select="/root/item"/>
</xsl:template>
<xsl:template match="item">
<xsl:if test="generate-id() = generate-id(key("item-by-value", normalize-space(.)))">
<xsl:value-of select="."/>
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="text()">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
Ta transformacja daje
ZA
b
do
re
- The
key()
odnośnik powyżej w szablonie dlaitem
zwraca zestaw węzłów zawierający wszystkieitem
elementy o takiej samej wartości ciągu, co węzeł kontekstu. - Jeśli zastosujesz funkcję, która oczekuje pojedynczego węzła na zestaw węzłów, będzie działać na pierwszym węźle w tym zestawie węzłów.
- Wszystkie połączenia do
generate-id()
gwarantują generowanie tego samego identyfikatora dla danego węzła podczas pojedynczego przejścia przez dokument. - Dlatego test będzie prawdą, jeśli węzeł kontekstu jest tym samym węzłem, co pierwszy zwracany przez
key()
połączenie.
3 dla odpowiedzi nr 3
Dla tych, którzy wciąż szukają odrębnego wyboru w XSLT:
Z XSLT 2.0, możesz użyć "odrębne wartości (/ doc / class / person / descriptive [(@ name =" age ")] / value)"
2 dla odpowiedzi № 4
Metoda Muenchiana wykorzystuje klucze do tworzenia unikatowej listy elementów z zestawu węzłów. Dla twoich danych klucz wyglądałby tak:
<!-- Set the name to whatever you want -->
<xsl:key name="PeopleAges" match="/doc/class/person/descriptive[@name = "age"]/value" use="." />
Stamtąd osobiście skorzystam xsl:apply-templates
ale możesz użyć następującego select
atrybut w innych miejscach:
<!-- you can change `apply-templates` to: `copy-of` or `for-each`. -->
<xsl:apply-templates select="/doc/class/person/descriptive[@name = "age"]/value[count(. | key("PeopleAges", .)[1]) = 1]" />
Dopasowanie towarzyszące powyższym jest o wiele prostsze:
<xsl:template match="person/descriptive[@name = "age"]/value">
<strong>Age: </strong><xsl:value-of select="." />
</xsl:template>
1 dla odpowiedzi nr 5
Aren "t brakuje odniesienia do" opisowe "zaraz po wartości poprzedzającej? Niektóre rzeczy takie jak następujące:
/doc/class/person/descriptive[(@name="age")][not(value=preceding-sibling::descriptive[@name="age"]/value)]/value
(Haven "t przetestował to)