XSLT跳过重复元素

Ank*_*ani 4 java xml xslt transformation

我是XSLT的初学者.

我的源XML如下:

<Passengers>
    <Passenger type="A" id="P1"/>
    <Passenger type="A" id="P2"/>
    <Passenger type="B" id="P3"/>
    <Passenger type="C" id="P4"/>
</Passengers>
Run Code Online (Sandbox Code Playgroud)

输出应如下:

<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>
Run Code Online (Sandbox Code Playgroud)

我已经创建了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>
Run Code Online (Sandbox Code Playgroud)

使用上面的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>
Run Code Online (Sandbox Code Playgroud)

如何省略或跳过重复元素?请帮忙.

Tim*_*m C 7

这实际上是分组问题的一个很好的例子.在XSLT1.0中,最有效的分组方法是使用一种称为"Muenchian分组"的技术,因此可能值得学习这一点.

在这种情况下,您希望按其@type属性对Passenger元素进行分组,因此您需要定义一个键来执行此操作

<xsl:key name="Passengers" match="Passenger" use="@type"/>
Run Code Online (Sandbox Code Playgroud)

然后,您需要选择Passenger元素,这些元素恰好是组中该元素首次出现的@type属性.这样做如下:

<xsl:apply-templates 
    select="Passenger[generate-id() = generate-id(key('Passengers', @type)[1])]"/>
Run Code Online (Sandbox Code Playgroud)

请注意使用generate-id为节点生成唯一ID,允许比较两个节点.

然后,为了计算组中出现的次数,它是直截了当的

<xsl:value-of select="count(key('Passengers', @type))"/>
Run Code Online (Sandbox Code Playgroud)

这是完整的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>
Run Code Online (Sandbox Code Playgroud)

应用于示例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>
Run Code Online (Sandbox Code Playgroud)

另请注意,没有理由使用xsl:element来输出静态元素.直接写出元素.