Removing duplicate in XSLT for node having multiple value

a 夏天 提交于 2020-01-07 02:22:35

问题


I have a sample XML which has duplicate node. Node 1 and Node3 with below temperature code and both values in FAH and CC are duplicate. All value within row node needs to be checked to checked to termed it as duplicate node

     <row>
                <attr name="temperatureCode">STORADE</attr>
                <attrQualMany name="temperature">
                        <value qual="FAH">10</value>
                        <value qual="CC">20</value>
                </attrQualMany>
        </row>

This sample message is

<document>
<party>
    <gtin>1000909090</gtin>
    <pos>
        <attrGroupMany name="temperatureInformation">
            <row>
                <attr name="temperatureCode">STORADE</attr>
                <attrQualMany name="temperature">
                    <value qual="FAH">10</value>
                    <value qual="CC">20</value>
                </attrQualMany>
            </row>
            <row>
                <attr name="temperatureCode">HANDLING</attr>
                <attrQualMany name="temperature">
                    <value qual="FAH">10</value>
                    <value qual="CC">20</value>
                </attrQualMany>
            </row>
            <row>
                <attr name="temperatureCode">STORADE</attr>
                <attrQualMany name="temperature">
                    <value qual="FAH">10</value>
                    <value qual="CC">20</value>
                </attrQualMany>
            </row>
            <row>
                <attr name="temperatureCode">DUMMY</attr>
                <attrQualMany name="temperature">
                    <value qual="FAH">10</value>
                    <value qual="CC">20</value>
                </attrQualMany>
            </row>
        </attrGroupMany>
    </pos>
</party>
</document>

When I apply the below XSLT, it works and duplicate node is removed. The XSLT which I am using is

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

<xsl:output indent="yes"/>

<xsl:key name="dummy" match="row" use="concat(attr[@name = 'temperatureCode'], '-', attrQualMany/value/@qual)"/>


<xsl:template match="document"> 
    <CatalogItem>
        <RelationshipData>
            <Relationship>
                <RelationType>temperatureInformation_details</RelationType>  
                <RelatedItems>      
                    <xsl:for-each select="party/pos/attrGroupMany[@name ='temperatureInformation']/row[generate-id() = generate-id(key('dummy', concat(attr[@name = 'temperatureCode'], '-', attrQualMany/value/@qual) ))]">                        
                        <RelatedItem>
                            <xsl:attribute name="referenceKey">
                                <xsl:value-of select="concat('temperatureInformation_details','-',attr[@name='temperatureCode'],'-',attrQualMany/@name,'-',attrQualMany/value/@qual,'-',attrQualMany/value,'-', position()    )"/>
                            </xsl:attribute>
                        </RelatedItem>


                    </xsl:for-each>

                </RelatedItems>
            </Relationship>
        </RelationshipData>
    </CatalogItem>

</xsl:template> 

</xsl:stylesheet>           

But it checks only the first value in attrQualMany name="temperature" and not both the values under attrQualMany.

If the sample message as below and it doesn't work for it. It should give me 4 records in output but it is giving me 3 records.

    <document>
    <party>
        <gtin>1000909090</gtin>
        <pos>
            <attrGroupMany name="temperatureInformation">
                <row>
                    <attr name="temperatureCode">STORADE</attr>
                    <attrQualMany name="temperature">
                        <value qual="FAH">10</value>
                        **<value qual="CC">20</value>**
                    </attrQualMany>
                </row>
                <row>
                    <attr name="temperatureCode">HANDLING</attr>
                    <attrQualMany name="temperature">
                        <value qual="FAH">10</value>
                        <value qual="CC">20</value>
                    </attrQualMany>
                </row>
                <row>
                    <attr name="temperatureCode">STORADE</attr>
                    <attrQualMany name="temperature">
                        <value qual="FAH">10</value>
                        **<value qual="CC">30</value>**
                    </attrQualMany>
                </row>
                <row>
                    <attr name="temperatureCode">DUMMY</attr>
                    <attrQualMany name="temperature">
                        <value qual="FAH">10</value>
                        <value qual="CC">20</value>
                    </attrQualMany>
                </row>
            </attrGroupMany>
        </pos>
    </party>
    </document>

The correct expected output is

    <?xml version="1.0" encoding="UTF-8"?>
    <CatalogItem>
   <RelationshipData>
      <Relationship>
         <RelationType>temperatureInformation_details</RelationType>
         <RelatedItems>
            <RelatedItem referenceKey="temperatureInformation_details-STORADE-temperature-FAH-10-1" />      
            <RelatedItem referenceKey="temperatureInformation_details-HANDLING-temperature-FAH-10-2" />
            <RelatedItem referenceKey="temperatureInformation_details-STORADE-temperature-FAH-10-3" /> 
             <RelatedItem referenceKey="temperatureInformation_details-DUMMY-temperature-FAH-10-4" />

         </RelatedItems>
      </Relationship>
   </RelationshipData>
    </CatalogItem>

Any input, please let me know


回答1:


If you want to group by three values, you must enumerate all three explicitly in the key:

<xsl:key name="grp" match="row" use="concat(attr[@name='temperatureCode'], '|', attrQualMany/value[@qual='FAH'], '|', attrQualMany/value[@qual='CC'])"/>

I suspect this could be shortened to:

<xsl:key name="grp" match="row" use="concat(attr, '|', attrQualMany/value[@qual='FAH'], '|', attrQualMany/value[@qual='CC'])"/>

Added:

The data can be changed under <attrQualMany name="temperature"> both for qual and its value. So I cannot hardcode to check the qual="FAH" or qual="CC". Is there any generic way without hardcoding the vaues.

If - and only if - the structure of attrQualMany is identical for all rows in the processed document, you can define your key as:

<xsl:key name="grp" match="row" use="concat(attr[@name='temperatureCode'], '|', attrQualMany[@name='temperature'])"/>

By "identical structure" I mean that in every row attrQualMany contains the same value children, with the same qual attributes, listed in the same order.

If the above condition is not true, you will have to process the document in two stages: first, concatenate all the values by which you want to group into a single text value; then group the resulting node-set by the concatenated value.



来源:https://stackoverflow.com/questions/38239500/removing-duplicate-in-xslt-for-node-having-multiple-value

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