 |
| XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead. |
Welcome to the p2p.wrox.com Forums.
You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
|
|
|
|

May 28th, 2013, 05:56 AM
|
|
Registered User
|
|
Join Date: May 2013
Posts: 4
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Merge XML files with multiple attributes
Hi,
I want to merge two XML files with same structure having multiple attributes. The sample files are:
XML1.xml
<DATA_LIST>
<DATA ins_type='Stock' und_ins_type='N.A.' is_generic='No' composite_quote='0'>Clean</DATA>
<DATA ins_type='Stock' und_ins_type='N.A.' is_generic='Yes' composite_quote='0'>Dirty</DATA>
<DATA ins_type='Bond' und_ins_type='N.A.' is_generic='No' composite_quote='0'>Clean</DATA>
<DATA ins_type='Bond' und_ins_type='N.A.' is_generic='Yes' composite_quote='0'>Dirty</DATA>
</DATA_LIST>
XML2.xml
<DATA_LIST>
<DATA ins_type='Stock' und_ins_type='N.A.' is_generic='No' composite_quote='0'>Dirty</DATA>
<DATA ins_type='Bond' und_ins_type='N.A.' is_generic='No' composite_quote='1'>Clean</DATA>
<DATA ins_type='FRN' und_ins_type='N.A.' is_generic='No' composite_quote='1'>Clean</DATA>
</DATA_LIST>
Output should be:
<DATA_LIST>
<DATA ins_type='Stock' und_ins_type='N.A.' is_generic='No' composite_quote='0'>Dirty</DATA>
<DATA ins_type='Stock' und_ins_type='N.A.' is_generic='Yes' composite_quote='0'>Dirty</DATA>
<DATA ins_type='Bond' und_ins_type='N.A.' is_generic='No' composite_quote='0'>Clean</DATA>
<DATA ins_type='Bond' und_ins_type='N.A.' is_generic='Yes' composite_quote='0'>Dirty</DATA>
<DATA ins_type='Bond' und_ins_type='N.A.' is_generic='No' composite_quote='1'>Clean</DATA>
<DATA ins_type='FRN' und_ins_type='N.A.' is_generic='No' composite_quote='1'>Clean</DATA>
</DATA_LIST>
Anybody please help!!!
Thanks,
Ashwini
|
|

May 28th, 2013, 02:03 PM
|
|
Registered User
|
|
Join Date: May 2013
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Hello ashwini kulsange,
As per my knowledge I written the code for your query, I checked with this code it's working, let me know if you have any better code.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/DATA_LIST">
<xsl:copy>
<xsl:apply-templates select="DATA"/>
<!-- <xsl:apply-templates select="document('XML1.xml')/*/DATA"/> -->
<xsl:apply-templates select="document('XML2.xml')/*/DATA"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
|
|

May 29th, 2013, 12:38 AM
|
|
Registered User
|
|
Join Date: May 2013
Posts: 4
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Thanks for your reply but your code will only merge two XML files. I want to override the XML2 to XML1 so as to avoid duplicate entries in the output. If you could look at my needed output all the tags are unique based on different attributes.
I have written a code to merge and override two XML's containing only one attribute @id which works perfectly.
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:copy>
<xsl:apply-templates select="*/*[not(@id = $updatexml/@id)]" />
<xsl:apply-templates select="$updatexml" />
</xsl:copy>
</xsl:template>
You can see i have checked for attribute @id while applying templates.
I want to implement something similar to this to merge/override files containing more than one attribute. As shown above my XML's contain four attributes.
|
|

May 29th, 2013, 11:25 AM
|
|
Registered User
|
|
Join Date: May 2013
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Thanks for your reply but i am confused with your code, "$updatexml" it is a variable and what is the path you mentioned for it, where we have to write.
If you don't mind can write your total code for this, then i can easily understand.
|
|

May 29th, 2013, 11:42 AM
|
|
Registered User
|
|
Join Date: May 2013
Posts: 4
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Hi,
Here is my code to merge two xml files that has only one attribute @id:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="cutomizations" select="document('./XML2.xml')/*/*"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:variable name="tag_name" select="name(/*)"/>
<xsl:element name="{$tag_name}">
<xsl:copy>
<xsl:apply-templates select="*/*[not(@id = $cutomizations/@id)]" />
<xsl:apply-templates select="$cutomizations" />
</xsl:copy>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
|
|

May 29th, 2013, 02:47 PM
|
|
Registered User
|
|
Join Date: May 2013
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Hi,
Thanks for your reply but while checking with your code i got result as
<DATA_LIST>
<DATA ins_type="Stock" und_ins_type="N.A." is_generic="No" composite_quote="0">Clean</DATA>
<DATA ins_type="Stock" und_ins_type="N.A." is_generic="Yes" composite_quote="0">Dirty</DATA>
<DATA ins_type="Bond" und_ins_type="N.A." is_generic="No" composite_quote="0">Clean</DATA>
<DATA ins_type="Bond" und_ins_type="N.A." is_generic="Yes" composite_quote="0">Dirty</DATA>
<DATA ins_type="Stock" und_ins_type="N.A." is_generic="No" composite_quote="0">Dirty</DATA>
<DATA ins_type="Bond" und_ins_type="N.A." is_generic="No" composite_quote="1">Clean</DATA>
<DATA ins_type="FRN" und_ins_type="N.A." is_generic="No" composite_quote="1">Clean</DATA>
</DATA_LIST>
The above result is not avoiding duplicate entries in the output, it look likes same as merging of two xml files.
The below code what you written is not checking any condition (it won't avoid any duplicate attributes). Check the below code once, I think you did some thing wrong in this
<xsl:template match="/">
<xsl:variable name="tag_name" select="name(/*)"/>
<xsl:element name="{$tag_name}">
<xsl:copy>
<xsl:apply-templates select="*/*[not(@id = $cutomizations/@id)]" />
<xsl:apply-templates select="$cutomizations" />
</xsl:copy>
</xsl:element>
</xsl:template>
I am using XALAN to test the code, in that i am giving the input as XML1.xml with your xslt code it look likes this
" java org.apache.xalan.xslt.Process -in XML1.xml -xsl merge.xsl > result.xml "
and also i want to know which processor(i mean xalan, saxan, xml spy, kernow ..etc) you are using for checking the desired output, and which one you are considering as a input xml for your xslt.
Check your code once again whether it providing exact result what you mentioned above expected output and reply me
Thank you
|
|

May 29th, 2013, 04:20 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
It's lazy to assume that we can infer the specification of this task from this one example. Are we to assume that if two elements are present in the two files with the same attributes but different content, then the element from the second file is to be used and the element from the first one discarded? If that's the case, why couldn't you say so?
Any task involving elimination of duplicates should be treated as a grouping problem. Grouping problems are easier in XSLT 2.0, especially when the element come from multiple documents. If you can use XSLT 2.0, then it's essentially
Code:
<xsl:for-each-group select="$doc1/DATA_LIST/DATA, $doc2/DATA_LIST/DATA" group-by="concat(@ins_type, '|', @und_ins_type, '|', @is_generic, '|', @is_composite_quote)">
<xsl:copy-of select="current-group()[1]"/>
</xsl:for-each-group>
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
|
|
 |