В XSL сделайте что-то вроде C #: list.Select (x => x.ID) .Distinct (); - PullRequest
1 голос
/ 11 декабря 2010

Мое намерение заключается в XSL, чтобы отображать только один раз текстовый узел для набора узлов с общим значением. Например, у меня есть следующий XML:

<Nodes>
    <Node att="1">A</Node>
    <Node att="1">B</Node>
    <Node att="2">C</Node>
    <Node att="2">D</Node>
    <Node att="3">E</Node>
</Nodes>

Мой вывод будет: "ACE".

Я не знаю, какими будут значения атрибута "att". Это может быть любая строка.

Любое предложение будет с благодарностью!

Ответы [ 3 ]

1 голос
/ 11 декабря 2010

Это можно сделать даже в одном выражении XPath :

/*/*[not(@att=preceding-sibling::*/@att)]/text()

Таким образом, упаковка в XSLT дает нам :

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

 <xsl:template match="/">
  <xsl:copy-of select="/*/*[not(@att=preceding-sibling::*/@att)]/text()"/>
 </xsl:template>
</xsl:stylesheet>

и применение этого к предоставленному документу XML:

<Nodes>
    <Node att="1">A</Node>
    <Node att="1">B</Node>
    <Node att="2">C</Node>
    <Node att="2">D</Node>
    <Node att="3">E</Node>
</Nodes>

дает требуемый, правильный результат :

ACE
0 голосов
/ 11 декабря 2010

Эта маленькая таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:key name="kNodeByAtt" match="Node" use="@att"/>
    <xsl:template match="Node[count(.|key('kNodeByAtt',@att)[1])!=1]"/>
</xsl:stylesheet>

Вывод:

ACE

Редактировать : просто для удовольствия решение XPath 2.0

string-join((/Nodes/Node)[index-of(/Nodes/Node/@att,@att)[1]],'')

Результат:

ACE
0 голосов
/ 11 декабря 2010

Это часто задаваемые вопросы. Смотри http://www.jenitennison.com/xslt/grouping/muenchian.html

Этот XSLT-код:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>

<xsl:key name="criteria" match="/Nodes/Node" use="@att"/>

<xsl:template match="Nodes">   
    <xsl:copy>
        <xsl:apply-templates select="Node[generate-id() = generate-id(key('criteria', @att))]"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="Node">
    <xsl:copy-of select="."/> <!-- Or other actions -->
</xsl:template>

</xsl:stylesheet>

Обеспечит желаемый (если я правильно понял) вывод:

<?xml version="1.0" encoding="UTF-8"?>
<Nodes>
   <Node att="1">A</Node>
   <Node att="2">C</Node>
   <Node att="3">E</Node>
</Nodes>

Это также будет работать с вводом, например:

<Nodes>
    <Node att="someRandomString">A</Node>
    <Node att="1aeawe">B</Node>
    <Node att="someRandomString">C</Node>
    <Node att="sfdf">D</Node>
    <Node att="">E</Node>
    <Node att="sfdf">F</Node>
</Nodes>

Вывод будет:

<?xml version="1.0" encoding="UTF-8"?>
<Nodes>
    <Node att="someRandomString">A</Node>
    <Node att="1aeawe">B</Node>
    <Node att="sfdf">D</Node>
    <Node att="">E</Node>
</Nodes>
...