XSLT 1.0 - Remove duplicates fields

南笙酒味 提交于 2019-12-08 06:09:34

问题


I'm having a problem with XSLT V1.0 with removing the duplicated nodes. I have this for entry

    <?xml version="1.0" encoding="utf-8"?>
<myRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Mappings>
        <Mapping fieldName="field1" >
        </Mapping>
        <Mapping fieldName="field1">
        </Mapping>
        <Mapping fieldName="field2" >
        </Mapping>
        <Mapping fieldName="field3" >
        </Mapping>
        <Mapping fieldName="field4">
        </Mapping>
    </Mappings>
</myRoot>

I have this XSL file

    <?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="xml" encoding="utf-8" indent="yes"/>

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

    <xsl:template match="Mappings">
        <xsl:if test="not(following::Mappings[Mapping/@fieldName=current()/Mapping/@fieldName])">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:if>       
    </xsl:template>


</xsl:stylesheet>

And I have the same entry XML file as result !!

How can I get rid of duplicated node () ?

I tried everything and no result :(

I tried Removing duplicates in xml with xslt Transform to remove duplicate and copy rest Removing consecutive duplicates with XSLT XSLT 1.0 textlist to individual elements and duplicate removal

......

What should I do to have this result ??

 <?xml version="1.0" encoding="utf-8"?>
    <myRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <Mappings>
            <Mapping fieldName="field1">
            </Mapping>
            <Mapping fieldName="field2" >
            </Mapping>
            <Mapping fieldName="field3" >
            </Mapping>
            <Mapping fieldName="field4">
            </Mapping>
        </Mappings>
    </myRoot>

Thanks


回答1:


The solution is very simple (no named templates and no use of xsl:call-template, only two templates, completely "push style"):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kFieldNameByVal" match="@fieldName" use="."/>

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

  <xsl:template match=
   "Mapping[not(generate-id(@fieldName)
           = generate-id(key('kFieldNameByVal', @fieldName)[1]))]"/>

</xsl:stylesheet>

When this transformation is applied on the provided XML document:

<myRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Mappings>
        <Mapping fieldName="field1" >
        </Mapping>
        <Mapping fieldName="field1">
        </Mapping>
        <Mapping fieldName="field2" >
        </Mapping>
        <Mapping fieldName="field3" >
        </Mapping>
        <Mapping fieldName="field4">
        </Mapping>
    </Mappings>
</myRoot>

the wanted, correct result is produced:

<myRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <Mappings>
      <Mapping fieldName="field1"/>
      <Mapping fieldName="field2"/>
      <Mapping fieldName="field3"/>
      <Mapping fieldName="field4"/>
   </Mappings>
</myRoot>



回答2:


The problem here is that your template is matching Mappings and attempting to exclude following duplicate Mappings elements, but there are none.

In either case, following:: and preceding:: are not good ways to select distinct values in XSLT. Instead, you should use Muenchian grouping:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:strip-space elements="*" />

  <xsl:key name="kMapping" match="Mapping" use="@fieldName"/>

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

  <xsl:template match="Mapping[generate-id() = 
                               generate-id(key('kMapping', @fieldName)[1])]">
    <xsl:call-template name="Copy" />
  </xsl:template>
  <xsl:template match="Mapping" />
</xsl:stylesheet>

When run on your sample input, this produces:

<myRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Mappings>
    <Mapping fieldName="field1" />
    <Mapping fieldName="field2" />
    <Mapping fieldName="field3" />
    <Mapping fieldName="field4" />
  </Mappings>
</myRoot>


来源:https://stackoverflow.com/questions/15551788/xslt-1-0-remove-duplicates-fields

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!