Hi all,
I am trying to merge 2 XML files that first of all i need to compare nodes of both files according to 2 attributes in the nodes. If those 3 attributes are equal, i need to replace the existing node with the new one. For example first xml file will be like; - <Root>
-
<Node Id ="1" FormId="form1" Value="value1"/>
-
<Node Id ="2" FormId="form1" Value="value2"/>
-
<Node Id ="3" FormId="form1" Value="value3"/>
-
</Root>
and second xml file will be like; - <Root>
-
<Node Id ="1" FormId="form1" Value="NewValue1"/>
-
<Node Id ="2" FormId="form1" Value="NewValue2"/>
-
<Node Id ="4" FormId="form1" Value="NewValue4"/>
-
</Root>
and when i merged these 2 files result should be; - <Root>
-
<Node Id ="1" FormId="form1" Value="NewValue1"/>
-
<Node Id ="2" FormId="form1" Value="NewValue2"/>
-
<Node Id ="3" FormId="form1" Value="value3"/>
-
<Node Id ="4" FormId="form1" Value="NewValue4"/>
-
</Root>
In those files, i compare the nodes of the second file with the nodes of the first file according to "Id" and "FormId" attributes. If those attributes are equal, that node in the first file will be replaced with the node in the second file. If they are not equal, current node in the second file will be written in the first file. What i have done so far is merging two xml files by comparing the distinct nodes according to all attributes in the nodes. But i couldn't manage only comparing nodes according to "Id" and "FormId" attributes. I am using that XSLT code to compare the equalty of the nodes and it works fine. - <xsl:for-each select="$node1/@*">
-
<xsl:if test="not($node2/@* [local-name()=local-name(current()) and namespace-uri()=namespace-uri(current()) and .=current()])">.</xsl:if>
-
</xsl:for-each>
When i changed that code only to compare according to those 2 attributes it doesn't work. - <xsl:for-each select="$node1/@*">
-
<xsl:if test="not($node2/@* [@Id = current()/@Id and @FormId = current()/@FormId])">.</xsl:if>
-
</xsl:for-each>
Any help would be appreciated.
12 18252 Dormilich 8,658
Recognized Expert Moderator Expert
you put in one attribute node too many. use $node2 instead of $node2/@*. 1)
a more elagant way would be without the if clause - <xsl:for-each select="$node1[@Id != $node2/@Id][@FormId != $node2/@FormId]">
-
// code goes here for every unique $node1
-
</xsl:for-each>
regards
1) - // your first condition
-
$node2/@* [@Id = current()/@Id]
-
// resolves to
-
$node2/@*/@Id = $node1/@*/@Id
-
// which returns true (both are empty/invalid) ...
Dormilich, thanks for your reply,
I tried what you recommended like the following; - <xsl:for-each select="$node1[@Id != $node2/@Id][@FormId != $node2/@FormId]">
-
<xsl:if test="not($node2/@*/@Id = $node1/@*/@Id and $node2/@*/@FormId = $node1/@*/@FormId)">.</xsl:if>
-
</xsl:for-each>
But it still gives the same output. What am i doing wrong?
Dormilich 8,658
Recognized Expert Moderator Expert
you misunderstood. my code doesn't require <xsl:if>. the for-each loop should select all unique elements of $node1 (so that you can copy them).
regards - <xsl:if test="not($node2/@*/@Id = $node1/@*/@Id and $node2/@*/@FormId = $node1/@*/@FormId)">.</xsl:if>
will always fail since there are no elements who fulfill this condition.
Explanation: - $node2/@*/@Id -> empty
-
$node1/@*/@Id -> empty
-
empty = empty -> true
-
not(true) -> false -> if statement skipped
Sorry for misunderstandin g. My XSLT code has two parts. First part compares the nodes and second part copies the nodes according to the results of comparation. When comparing if required attributes are equal, i need to get a "=" and after that update the node. If attributes are not equal, i need to get a "!" and then copy the node from second file to the first file. Below is the comparation part of the code. - <!--
-
Comparing single nodes:
-
if $node1 and $node2 are equivalent then the template creates a
-
text node "=" otherwise a text node "!" -->
-
<xsl:template name="m:compare-nodes">
-
<xsl:param name="node1" />
-
<xsl:param name="node2" />
-
<xsl:variable name="type1">
-
<xsl:apply-templates mode="m:detect-type" select="$node1" />
-
</xsl:variable>
-
<xsl:variable name="type2">
-
<xsl:apply-templates mode="m:detect-type" select="$node2" />
-
</xsl:variable>
-
<xsl:choose>
-
<!-- Are $node1 and $node2 element nodes with the same name? -->
-
<xsl:when test="$type1='element' and $type2='element' and local-name($node1)=local-name($node2) and namespace-uri($node1)=namespace-uri($node2) and name($node1)!=$dontmerge and name($node2)!=$dontmerge">
-
<!-- Comparing the attributes -->
-
<xsl:variable name="diff-att">
-
<!-- same number ... -->
-
<xsl:if test="count($node1/@*)!=count($node2/@*)">.</xsl:if>
-
<!-- ... and same name/content -->
-
<xsl:for-each select="$node1/@*">
-
<!--<xsl:for-each select="$node1/Caption">-->
-
<xsl:value-of select="@Id" />
-
<xsl:value-of select="@FormId" />
-
<xsl:value-of select="@LangId" />
-
<!--<xsl:if test="not($node2/Caption/Id/FormId/LangId [local-name()=local-name(current()) and namespace-uri()=namespace-uri(current()) and .=current()])">.</xsl:if>-->
-
<xsl:if test="not($node2/@* [local-name()=local-name(current()) and namespace-uri()=namespace-uri(current()) and .=current()])">.</xsl:if>
-
</xsl:for-each>
-
</xsl:variable>
-
<xsl:choose>
-
<xsl:when test="string-length($diff-att)!=0">!</xsl:when>
-
<xsl:otherwise>=</xsl:otherwise>
-
</xsl:choose>
-
</xsl:when>
-
<!-- Other nodes: test for the same type and content -->
-
<xsl:when test="$type1!='element' and $type1=$type2 and name($node1)=name($node2) and ($node1=$node2 or ($normalize='yes' and normalize-space($node1)= normalize-space($node2)))">=</xsl:when>
-
<!-- Otherwise: different node types or different name/content -->
-
<xsl:otherwise>!</xsl:otherwise>
-
</xsl:choose>
-
</xsl:template>
Sorry i don't know much about XSLT so i have difficulty in solving the problem.
Regards,
Anybody knows how to fix that??
Dormilich 8,658
Recognized Expert Moderator Expert
if you just (well...) want to merge two files, why making it by the means of a comparison string? Isn't that complicated (well, it looks so...)?
As I (hopefully) understand you right you want to merge two xml files omitting duplicate nodes (regarding the attributes) from the first xml. Do you need "!" and "=" in the output too?
I'd do a straightforward merging.
the idea is to copy all nodes from xml no.2 and add all nodes from xml no.1 that are not present in xml no.2.
like (sketch) - // select mergable nodes
-
<xsl:variable name="node1" select="//*[self::name() != $dontmerge]"/>
-
//... there may be more conditions depending on the xml
-
-
<xsl:template match="/">
-
<xsl:apply-templates/>
-
</xsl:template>
-
-
// add xml no.2
-
<xsl:template match="$node2">
-
<xsl:copy-of select="."/> // or whatever value you need
-
</xsl:template>
-
-
// add xml no.1 using conditions
-
<xsl:template match="$node1[@Id != $node2/@Id][@FormId != $node2/@FormId]">
-
<xsl:copy-of select="."/> // or whatever value you need
-
</xsl:template>
this idea should at least work for your example....
regards
Thanks again for your reply. In your code i can only insert the nodes which doesn't exist in the file1. But i also want to replace the nodes having the same "Id" and "FormId" attribute values. For ex. if i have a line in file1 like; - <Node Id="1" FormId="form1" Values="value1">
and a line in file2 like; - <Node Id="1" FormId="form1" Values="new Value">
which both nodes have same "Id" and "FormId" attribute values("1" and "form1") and corresponding output will be; - <Node Id="1" FormId="form1" Values="new Value">
that first node will be replaced with second node. So i have two options according to what i get from the comparation("!" or "="). If result is "!" i will insert the node from the file2 to file1, and if result is "=" i will replace the node(as in the example above). So is it possible to modify the code i give to get a result "!" or "=" according to the values of "Id" and "FormId" attributes.
Hope it is obvious to understand.
Regards
jkmyoung 2,057
Recognized Expert Top Contributor
Sorry if I'm misinterpreting (my mind isn't working that well yet today).
Are you sorting based on id? Is it possible to have the same id, but different FormId?
Would have suggested a 1-liner:
<xsl:copy-of select="$node1[not ($node2[@Id = current()/@Id])] | $node2"/>
or if order matters, change to a for-each: -
<xsl:for-each select="$node1[not ($node2[@Id = current()/@Id])] | $node2">
-
<xsl:sort select="@Id" order="ascending"/>
-
<xsl:copy-of select="."/>
-
</xsl:for-each>
-
Otherwise, I agree with Dormilich about the xpath being wrong. (attributes don't have children attributes)
---
I think we're going about the same problem 2 different ways.
If we're going to 'update' the old node with new values, why not just copy the new node?
Of course it may have the same Id and different FormId and i can already copy the node in the merge part. And in the xml files attributes don't have child attributes(i know it is impossible). Just each node has attributes ("Id", "FormId", "Values"). Merging part of the XSLT file can copy the nodes correctly. But when i comparing the nodes("m:compar e-nodes" template i sent in one of the messages above) i always get a "!" that shows nodes are not equal(eventhoug h "Id" and "FormId" attribute values are equal). I only want to get the correct output ("!" or "=") from the compare template. By the way i don't need to sort the nodes. Here i need to modify the above "m:compare-nodes" template.
Regards
Sign in to post your reply or Sign up for a free account.
Similar topics |
by: Iain |
last post by:
I want to create an XML configuration file which might look like
<REGION Name="Europe" WingDing="Blue">
<COUNTRY Name="UK" WingDing="white">
<TOWN Name="London" WingDing="Orange" />
</COUNTRY>
</REGION>
<REGION Name="NorthAmerica" WingDing="Yellow">
<COUNTRY Name="Canada">
<TOWN Name="Quebec" WingDing="Brown" />
|
by: inquirydog |
last post by:
Hi-
Does anyone know a way to compare whether two nodes contain
the same information in xslt (the name, attributes, and all content
recursivly should be the same. I am interested in the case where node
ordering matters, and also the case where it doesn't, but perhaps that
is an advanced topic). Ideally the method should be available to...
|
by: Jon Martin Solaas |
last post by:
Hi,
I have a general document somewhat like this:
--------------------------------------
<root>
<level1>
<level2>
<interestingstuff number="2"/>
<interestingstuff number="3"/>
<interestingstuff number="1"/>
|
by: Stephan Brunner |
last post by:
Hi
I have created two flavors of an XSLT stylesheet to transform all attributes
of an XML document to elements:
They both work as expected with MSXML and XMLSPY but throw an exception
=========================
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0"
|
by: Alex |
last post by:
I stumbled upon this while developing a custom XPathNavigator.
It appears that copy action for attributes is broken in the .net
framework XSLT processor.
The intent was to just copy the entities and attributes from the
source XML into the output using simple "identity" like XSLT:
<xsl:stylesheet...
| |
by: Ian Roddis |
last post by:
Hello,
I want to embed SQL type queries within an XML data record. The XML
looks something like this:
<DISPLAYPAGE>
<FIELD NAME="SERVER" TYPE="DROPDOWN">
<OPTION>1<OPTION>
<OPTION>2<OPTION>
<OPTION>3<OPTION>
</FIELD>
|
by: Foxpointe |
last post by:
Given some arbitrary XHTML, I'd like to obtain a 'simplified' XHTML
result which strips out a large subset of standard elements and
attributes - but not all. The main things I would like to accomplish:
1) Provide a list of elements/attributes to be stripped (i.e. everything
else should be passed through) or those that should be passed...
|
by: byquestion |
last post by:
Hi there xslt gurus,
i am kinda new to xslt and having difficulty to implement my some iterations. i need to recreate an xml file by using xslt. here is the sample xml file(input for xslt)
<Flights>
<Flight>
<FlightLeg >
<BookingClassCodeList>
<BookingCode Value="C" />
<BookingCode Value="Y" />
...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it. ...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
| |
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules.
He will explain when you may want to use classes...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one.
At the time of converting from word file to html my equations which are in the word document file was convert...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols.
I succeeded, with both firewalls in...
|
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
|
by: bsmnconsultancy |
last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...
| |