问题
I have the following XML document:
<?xml version="1.0" encoding="UTF-8"?>
<cars>
<car body="Wagon">
<text>Red</text>
</car>
<car body="Sedan">
<text>Yellow</text>
</car>
<car body="Sedan">
<text></text>
</car>
<car body="Wagon">
<textlist>
<text>Red</text>
<text>Green</text>
<text>Black</text>
<text>Blue</text>
</textlist>
</car>
<car body="Sedan">
<textlist>
<text>Yellow</text>
<text>Orange</text>
</textlist>
</car>
<car body="Fastback">
<textlist>
<text>Yellow</text>
<text>Red</text>
<text>Green</text>
<text>Black</text>
<text>Blue</text>
</textlist>
</car>
<car body="Fastback">
<textlist>
<text>Pink</text>
<text>Red</text>
<text>Orange</text>
</textlist>
</car>
</cars>
Using XSLT 1.0 I need to transform the XML document to this format:
<?xml version="1.0" encoding="UTF-8"?>
<cars>
<car type="Wagon">Red</car>
<car type="Sedan">Yellow</car>
<car type="Wagon">Green</car>
<car type="Wagon">Black</car>
<car type="Wagon">Blue</car>
<car type="Sedan">Orange</car>
</cars>
Notice that:
- body="Fastback" is excluded
- Duplicates are excluded (Red Wagon appears twice)
- Textlist multiple items are put as individual elements in the output XML
- Ignore empty values
回答1:
Here is a sample:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:key name="k1"
match="car[not(@body = 'Fastback')]//text"
use="concat(ancestor::car/@body, '|', .)"/>
<xsl:template match="cars">
<xsl:copy>
<xsl:apply-templates select="car[not(@body = 'Fastback')]//text
[generate-id() = generate-id(key('k1', concat(ancestor::car/@body, '|', .))[1])]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text">
<car type="{ancestor::car/@body}">
<xsl:value-of select="."/>
</car>
</xsl:template>
</xsl:stylesheet>
It uses Muechian grouping, see http://www.jenitennison.com/xslt/grouping/muenchian.xml if you are not familiar with that XSLT 1.0 approach.
来源:https://stackoverflow.com/questions/11467010/xslt-1-0-textlist-to-individual-elements-and-duplicate-removal