删除基于元素标记的重复节点集为空

时间:2016-12-13 15:43:31

标签: xml xslt xslt-1.0 bpel

***This is my input xml coming from source.***

<?xml version="1.0" encoding="UTF-8" ?>
<exampleElement xmlns="http://www.example.org">
<element1>
  <Id>123</Id>
  <Name>Imag</Name>
  <Status>active</Status>
  <EndDate/>
</element1>
<element1>
  <Id>888</Id>
  <Name>Preci</Name>
  <Status>active</Status>
  <EndDate/>
</element1>    
<element1>
  <Id>123</Id>
  <Name>Imag</Name>
  <Status>terminated</Status>
  <EndDate>2016-12-10</EndDate>
</element1>
<element1>
<Id>143</Id>
<Name>kilok</Name>
<Status>terminated</Status>
<EndDate>2016-11-10</EndDate>
</element1>
</exampleElement>

在上面的输入数据中,两组重复不同的值。其中ID = 123元素节点有两条记录,其中EndDate值为EndDate。

**I want out put in this below format where one record set 
from duplicates with EndDate tag empty.**

<?xml version = '1.0' encoding = 'UTF-8'?>
<ns1:exampleElement xmlns:ns1="http://www.example.org">
<ns1:element1>
  <ns1:Id>888</ns1:Id>
  <ns1:Name>Preci</ns1:Name>
  <ns1:Status>active</ns1:Status>
  <ns1:EndDate/>
</ns1:element1>
<ns1:element1>
  <ns1:Id>123</ns1:Id>
  <ns1:Name>Imag</ns1:Name>
  <ns1:Status>active</ns1:Status>
  <ns1:EndDate/>
</ns1:element1>
<ns1:element1>
  <ns1:Id>143</ns1:Id>
  <ns1:Name>Kilok</ns1:Name>
  <ns1:Status>terminated</ns1:Status>
  <ns1:EndDate>2016-11-10</ns1:EndDate>
  </ns1:element1>
</ns1:exampleElement>

请在下面找到我的xslt,这将提供唯一的记录,但我想根据价值获得唯一记录。

<xsl:template match="/">
<ns1:exampleElement>
  <xsl:for-each select="/ns1:exampleElement/ns1:element1[not(ns1:Id=following::ns1:Id)]">
    <ns1:element1>
      <ns1:Id>
        <xsl:value-of select="./ns1:Id"/>
      </ns1:Id>
      <ns1:Name>
        <xsl:value-of select="./ns1:Name"/>
      </ns1:Name>
      <ns1:Status>
        <xsl:value-of select="./ns1:Status"/>
      </ns1:Status>
      <ns1:EndDate>
        <xsl:value-of select="./ns1:EndDate"/>
      </ns1:EndDate>
    </ns1:element1>
  </xsl:for-each>
</ns1:exampleElement>

因为源系统将在第一组中接收用户Active记录并在第二组中接收终止记录,但我们只需要将活动记录转发到目标系统。请帮忙。

1 个答案:

答案 0 :(得分:0)

您在评论中获得了Muenchian Grouping的文章链接,该文章解释了采取的方法。它涉及首先定义一个键以匹配您想要分组的元素(其中ns1是绑定到名称空间URI的名称空间前缀)

<xsl:key name="elements" match="ns1:element1" use="ns1:Id" /> 

然后,为了获得不同的(或者更确切地说,Id的每个可能值的第一次出现的元素),你会这样做...

<xsl:for-each select="ns1:element1[generate-id() = generate-id(key('elements', ns1:Id)[1])]" />

要访问组中的所有元素,请执行此操作..

<xsl:for-each select="key('elements', ns1:Id)">

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="http://www.example.org">  
   <xsl:key name="elements" match="ns1:element1" use="ns1:Id" /> 

   <xsl:output method="xml" indent="yes" />

   <xsl:template match="/">
        <xsl:copy>
            <xsl:for-each select="*/ns1:element1[generate-id() = generate-id(key('elements', ns1:Id)[1])]">
                <xsl:for-each select="key('elements', ns1:Id)">
                    <xsl:sort select="ns1:EndDate" />
                    <xsl:if test="position() = 1">
                        <xsl:apply-templates select="." />
                    </xsl:if>
                </xsl:for-each>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

如果您真的想要输出带有ns1:前缀的XML(虽然它确实不会产生影响),请尝试使用

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="http://www.example.org">  
   <xsl:key name="elements" match="ns1:element1" use="ns1:Id" /> 

   <xsl:output method="xml" indent="yes" />

   <xsl:template match="/">
        <ns1:exampleElement>
            <xsl:for-each select="*/ns1:element1[generate-id() = generate-id(key('elements', ns1:Id)[1])]">
                <xsl:for-each select="key('elements', ns1:Id)">
                    <xsl:sort select="ns1:EndDate" />
                    <xsl:if test="position() = 1">
                        <xsl:apply-templates select="." />
                    </xsl:if>
                </xsl:for-each>
            </xsl:for-each>
        </ns1:exampleElement>
    </xsl:template>

    <xsl:template match="*" priority="2">
        <xsl:element name="ns1:{local-name()}">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>