我是XSLT的初学者。
My Source XML如下:
<Passengers>
<Passenger type="A" id="P1"/>
<Passenger type="A" id="P2"/>
<Passenger type="B" id="P3"/>
<Passenger type="C" id="P4"/>
</Passengers>
输出应如下:
<Pax_Items>
<Item>
<Type>A</Type>
<Count>2</Count>
</Item>
<Item>
<Type>B</Type>
<Count>1</Count>
</Item>
<Item>
<Type>C</Type>
<Count>1</Count>
</Item>
</Pax_Items>
我已经创建了XSLT,如下所示
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0" exclude-result-prefixes="xmlns">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:variable name="filter" select="'TK,AJ'"/>
<xsl:template match="Passengers">
<xsl:element name="Pax_Items">
<xsl:apply-templates select="Passenger"/>
</xsl:element>
</xsl:template>
<xsl:template match="Passenger">
<xsl:element name="Item">
<xsl:element name="Type">
<xsl:value-of select="@type"/>
</xsl:element>
<xsl:element name="Count">
<xsl:value-of select="count(//Passenger[@type=current()/@type])"/>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
使用上面的XSLT我得到了以下输出:
<Pax_Items>
<Item>
<Type>A</Type>
<Count>2</Count>
</Item>
<Item>
<Type>A</Type>
<Count>2</Count>
</Item>
<Item>
<Type>B</Type>
<Count>1</Count>
</Item>
<Item>
<Type>C</Type>
<Count>1</Count>
</Item>
</Pax_Items>
如何省略或跳过重复元素?请帮忙。
答案 0 :(得分:7)
这实际上是分组问题的一个很好的例子。在XSLT1.0中,最有效的分组方法是使用一种称为“Muenchian分组”的技术,因此可能值得学习这一点。
在这种情况下,您希望按 @type 属性对 Passenger 元素进行分组,因此您需要定义一个键来执行此操作
<xsl:key name="Passengers" match="Passenger" use="@type"/>
然后,您需要选择 Passenger 元素,这些元素恰好是 @type 属性中该元素首次出现的元素。这样做如下:
<xsl:apply-templates
select="Passenger[generate-id() = generate-id(key('Passengers', @type)[1])]"/>
请注意使用 generate-id 为节点生成唯一ID,允许比较两个节点。
然后,要计算组中出现的次数,它是直截了当的
<xsl:value-of select="count(key('Passengers', @type))"/>
这是完整的XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="Passengers" match="Passenger" use="@type"/>
<xsl:template match="Passengers">
<Pax_Items>
<xsl:apply-templates select="Passenger[generate-id() = generate-id(key('Passengers', @type)[1])]"/>
</Pax_Items>
</xsl:template>
<xsl:template match="Passenger">
<Item>
<Type>
<xsl:value-of select="@type"/>
</Type>
<Count>
<xsl:value-of select="count(key('Passengers', @type))"/>
</Count>
</Item>
</xsl:template>
</xsl:stylesheet>
当应用于您的示例XML时,输出以下内容
<Pax_Items>
<Item>
<Type>A</Type>
<Count>2</Count>
</Item>
<Item>
<Type>B</Type>
<Count>1</Count>
</Item>
<Item>
<Type>C</Type>
<Count>1</Count>
</Item>
</Pax_Items>
另请注意,没有理由使用 xsl:element 来输出静态元素。直接写出元素。
答案 1 :(得分:2)
更新您的passenger
模板,如下所示;我添加了if条件来检查重复的节点,
<xsl:template match="Passenger">
<xsl:if test="not(preceding-sibling::Passenger[@type = current()/@type])">
<xsl:element name="Item">
<xsl:element name="Type">
<xsl:value-of select="@type"/>
</xsl:element>
<xsl:element name="Count">
<xsl:value-of select="count(//Passenger[@type=current()/@type])"/>
</xsl:element>
</xsl:element>
</xsl:if>
</xsl:template>