Solved

Merging two XML files into one part 3

Posted on 2006-07-13
11
513 Views
Last Modified: 2008-01-09
Hi,
Once more the clients have changed how they want the layout of the XML file to look again.
I need to modify the XML merge I got here
http://www.experts-exchange.com/Web/Web_Languages/XML/Q_21872528.html
and then had modified here,
http://www.experts-exchange.com/Web/Web_Languages/XML/Q_21872528.html

to include the following additions:

following is a sample of the controls for existing file:
   <controls>
      <control id="1" TextType="Single" LineCount="1">
         <language code="design">
            <value text="SingleControl1" line="1" />
         </language>
      </control>
 
      <control id="2" TextType="Single" LineCount="1">
         <language code="design">
            <value text="SingleControl2" line="1" />
         </language>
         <language code="fr">
            <value text="SingleControl2_fr" line="1" />
         </language>
      </control>
   </controls>

and following is a sample of the new file to be merged into it:
   <controls>
      <control id="1" TextType="Single" LineCount="1">
         <language code="design">
            <value text="SingleControl1" line="1" />
         </language>
         <language code="fr">
            <value text="SingleControl1_fr" line="1" />
         </language>
      </control>
      <control id="2" TextType="Single" LineCount="1">
         <language code="it">
            <value text="SingleControl2_it" line="1" />
         </language>
      </control>

      <control id="3" TextType="List" LineCount="3">
         <language code="design">
            <value text="SingleControl3a" line="1" />
            <value text="SingleControl3b" line="2" />
            <value text="SingleControl3c" line="3" />
         </language>
         <language code="fr">
            <value text="SingleControl3a_fr" line="1" />
            <value text="SingleControl3b_fr" line="2" />
            <value text="SingleControl3c_fr" line="3" />
         </language>
      </control>
   </controls>

Once merged it is producing the following:
   <controls>
      <control id="1" TextType="Single" LineCount="1">
         <language code="design">
            <value text="SingleControl1" line="1" />
         </language>
         <language code="fr">
            <value text="SingleControl1_fr" line="1" />
         </language>
      </control>
      <control id="2" TextType="Single" LineCount="1">
         <language code="design">
            <value text="SingleControl2" line="1" />
         </language>
         <language code="fr">
            <value text="SingleControl2_fr" line="1" />
         </language>
         <language code="it">
            <value text="SingleControl2_it" line="1" />
         </language>
      </control>
   </controls>

where it should produce :

   <controls>
      <control id="1" TextType="Single" LineCount="1">
         <language code="design">
            <value text="SingleControl1" line="1" />
         </language>
         <language code="fr">
            <value text="SingleControl1_fr" line="1" />
         </language>
      </control>
      <control id="2" TextType="Single" LineCount="1">
         <language code="design">
            <value text="SingleControl2" line="1" />
         </language>
         <language code="fr">
            <value text="SingleControl2_fr" line="1" />
         </language>
         <language code="it">
            <value text="SingleControl2_it" line="1" />
         </language>
      </control>
************************************************************************
***** The following part is not being copied to the new file. *****
************************************************************************
      <control id="3" TextType="List" LineCount="3">
         <language code="design">
            <value text="SingleControl3a" line="1" />
            <value text="SingleControl3b" line="2" />
            <value text="SingleControl3c" line="3" />
         </language>
         <language code="fr">
            <value text="SingleControl3a_fr" line="1" />
            <value text="SingleControl3b_fr" line="2" />
            <value text="SingleControl3c_fr" line="3" />
         </language>
      </control>
************************************************************************
   </controls>
0
Comment
Question by:scotdance
  • 6
  • 5
11 Comments
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 17103400
Hi Stuart,

If I understand well enough what you need
(a mechanism that copies the entire node of the new file if the id doesn't exist in the mainfile)
all you need is a template for controls
that does the normal processing first
but then does a copy-of of all ids not found in the main file
(in the for each loop)

   <xsl:template match="controls">
      <xsl:param name="ctr" select="."/>
      <xsl:param name="sec_ctr" select="document('languages_new.xml')//controls" />
      <xsl:copy>
         <xsl:copy-of select="@*"/>
         <xsl:apply-templates select="node() | text()"/>
         <xsl:for-each select="$sec_ctr/control[not(@id = $ctr/control/@id)]">
            <xsl:copy-of select="."/>
         </xsl:for-each>
      </xsl:copy>
   </xsl:template>


Cheers!

Geert
0
 

Author Comment

by:scotdance
ID: 17106365
Hi,
Thanks for that seems to work good, only problem now is the part i wrote to copy the missing values from an ID that already exists seems to have stopped, here is what i wrote, i based it on the earlier code you gave me for the 'charmaps' nodes in the xml, i did have it working but now i have broke it. lol
Perhaps you can see what i've done wrong in it,
Thanks again,

<!-- Copy 'value' into merged file. -->
   <xsl:template match="value">
      <xsl:param name="parentCode" select="../@code" />

      <xsl:param name="mainVal" select="value" />

      <xsl:param name="secVal" select="document('languages_new.xml')//value[ancestor::language/@code = $parentCode]" />

      <xsl:copy>
         <xsl:copy-of select="$mainVal" />

         <xsl:copy-of select="$secVal[not(@id = $mainVal/@id)]" />
      </xsl:copy>
   </xsl:template>
0
 

Author Comment

by:scotdance
ID: 17106449
Just had a look at my example it wasn't clear enough to describe what i was after with the values being copied sorry, here is a better example of it:

Orignal file:
   <controls>
      <control id="1" TextType="Single" LineCount="1">
         <language code="design">
            <value text="SingleControl1" line="1" />
         </language>
      </control>
  </controls>

and following is a sample of the new file to be merged into it:
   <controls>
      <control id="1" TextType="Single" LineCount="1">
         <language code="design">
            <value text="SingleControl1" line="1" />
            <value text="SingleControl1" line="2" />
            <value text="SingleControl1" line="3" />
         </language>
         <language code="fr">
            <value text="SingleControl1_fr" line="1" />
         </language>
      </control>
  </controls>

output file should look like:
   <controls>
      <control id="1" TextType="Single" LineCount="1">
         <language code="design">
            <value text="SingleControl1" line="1" />
            <value text="SingleControl1" line="2" />
            <value text="SingleControl1" line="3" />
         </language>
         <language code="fr">
            <value text="SingleControl1_fr" line="1" />
         </language>
      </control>
  </controls>

Thanks again for your help.  
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 17106494
maybe you just have to change thes lines
        <xsl:for-each select="$sec_ctr/control[not(@id = $ctr/control/@id)]">
            <xsl:copy-of select="."/>
         </xsl:for-each>

in an active deep copy, like this
        <xsl:for-each select="$sec_ctr/control[not(@id = $ctr/control/@id)]">
             <xsl:copy>
                  <xsl:copy-of select="@*"/>
                  <xsl:apply-templates select="node() | text()"/>
              </xsl:copy>
        </xsl:for-each>

this makes the other templates active on this part
0
 

Author Comment

by:scotdance
ID: 17106698
Hi,
nope that did not work it did not copy the value from the second file, it also stopped your orignal code on here from working :(

I was thinking of something similar to what you said, but making it a seperate template.  
My problem was that i was also adding in the values from the other nodes in the dynamictext that are in the orignal xml file. so i was getting the control text as well as the dynamic text.

Once this is up and running, if the clients want it changed again they'll be told no, lol.

Cheers
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 60

Accepted Solution

by:
Geert Bormans earned 25 total points
ID: 17108667
I had a look at your template for controls

this could be it

  <xsl:template match='control | dynamictext'>
      <xsl:param name="cid" select="@id" />

      <xsl:param name="elName" select="name()" />

      <xsl:param name="mainlang" select="language" />

      <xsl:param name="seclang" select="document('languages_new.xml')//*[name() = $elName][@id = $cid]/language" />

      <xsl:copy>
         <xsl:copy-of select="@*" />
         <xsl:for-each select="$mainlang">
            <xsl:variable name="thisLang" select="."/>
            <xsl:copy>
               <xsl:copy-of select="@*"/>
               <xsl:copy-of select="value"/>
               <xsl:copy-of select="$seclang[@code = $thisLang/@code]/value[not(@line = $thisLang/value/@line)]"/>
            </xsl:copy>
         </xsl:for-each>
         <xsl:copy-of select="$mainlang" ></xsl:copy-of>

         <xsl:copy-of select="$seclang[not(@code = $mainlang/@code)]" />
      </xsl:copy>
   </xsl:template>
0
 

Author Comment

by:scotdance
ID: 17120798
Hi,
Just tried that and it was not adding the missing root nodes("dynamictext" and "control") for the control and dynamictext nodes,
and when it was adding the "language" child nodes of existing nodes, it was adding the child nodes from the orignal file but then below them it was adding the childnodes from the new file.

for example:
orignal file,
      <dynamictext id="7" TextType="List" LineCount="3" ftype="form" dhint="Hint 7">
         <language code="design">
            <value text="Hint 7a" line="1" />
            <value text="Hint 7b" line="2" />
            <value text="Hint 7c" line="3" />
         </language>
         <language code="fr">
            <value text="Hint 7a_fr" line="1" />
         </language>
         <language code="it">
            <value text="Hint 7a_it" line="1" />
         </language>
         <language code="ae">
            <value text="&#1575;&#1607;&#1609;&#1601; 7&#1588;" line="1" />
            <value text="&#1571;&#1607;&#1609;&#1601; 7&#1604;&#1575;" line="2" />
            <value text="&#1571;&#1607;&#1609;&#1601; 7&#1572;" line="3" />
         </language>
      </dynamictext>

new file,
      <dynamictext id="7" TextType="List" LineCount="3" ftype="form" dhint="Hint 7">
         <language code="fr">
            <value text="Hint 7a_fr" line="1" />
            <value text="Hint 7b_fr" line="1" />
            <value text="Hint 7c_fr" line="1" />
         </language>
         <language code="it">
            <value text="Hint 7a_it" line="1" />
            <value text="Hint 7b_it" line="1" />
            <value text="Hint 7c_it" line="1" />
         </language>
         <language code="de">
            <value text="Hint 8a_fr" line="1" />
         </language>
      </dynamictext>
      <dynamictext id="8" TextType="List" LineCount="3" ftype="form" dhint="Hint 7">
         <language code="design">
            <value text="Hint 8a" line="1" />
            <value text="Hint 8b" line="2" />
            <value text="Hint 8c" line="3" />
         </language>
         <language code="fr">
            <value text="Hint 8a_fr" line="1" />
         </language>
      </dynamictext>

merged file was like this,
     <dynamictext id="7" TextType="List" LineCount="3" ftype="form" dhint="Hint 7">
         <language code="design">
            <value text="Hint 7a" line="1" />
            <value text="Hint 7b" line="2" />
            <value text="Hint 7c" line="3" />
         </language>
         <language code="fr">
            <value text="Hint 7a_fr" line="1" />
         </language>
         <language code="it">
            <value text="Hint 7a_it" line="1" />
         </language>
         <language code="ae">
            <value text="&#1575;&#1607;&#1609;&#1601; 7&#1588;" line="1" />
            <value text="&#1571;&#1607;&#1609;&#1601; 7&#1604;&#1575;" line="2" />
            <value text="&#1571;&#1607;&#1609;&#1601; 7&#1572;" line="3" />
         </language>
         <language code="design">
            <value text="Hint 7a" line="1" />
            <value text="Hint 7b" line="2" />
            <value text="Hint 7c" line="3" />
         </language>
         <language code="fr">
            <value text="Hint 7a_fr" line="1" />
         </language>
         <language code="it">
            <value text="Hint 7a_it" line="1" />
         </language>
         <language code="ae">
            <value text="&#1575;&#1607;&#1609;&#1601; 7&#1588;" line="1" />
            <value text="&#1571;&#1607;&#1609;&#1601; 7&#1604;&#1575;" line="2" />
            <value text="&#1571;&#1607;&#1609;&#1601; 7&#1572;" line="3" />
         </language>
         <language code="de">
            <value text="Hint 8a_fr" line="1" />
         </language>
      </dynamictext>

as you can see it never copied the id = 8 node and the language nodes have been doubled,
I have wrote this function:

   <xsl:template match="dynamictexts">
      <xsl:param name="dyn" select="." />

      <xsl:param name="sec_dyn" select="document('languages_new.xml')//dynamictexts" />

      <xsl:copy>
         <xsl:copy-of select="@*" />

         <xsl:apply-templates select="node() | text()" />

         <xsl:for-each select="$sec_dyn/dynamictext[not(@id = $dyn/dynamictext/@id)]">
            <xsl:copy-of select="." />
         </xsl:for-each>
      </xsl:copy>
   </xsl:template>

which copies the missing "dynamictext" nodes, but does not copy the missing "langauge" and "value" nodes of existing "dynamictext" nodes.  
Not sure if this is correct or not, but is it be possible to edit this function to allow the "language" and "value" of existing nodes to be copied if missing, or am i going the wrong way.
Thanks for your help.
ScotDance
0
 

Author Comment

by:scotdance
ID: 17136721
Hi,
I've been playing with the code you gave me and have managed to get it to partially work with a slight modification,

here it is with the changes i made:

<!-- Merge the control and dynamictext child nodes from each file into one file.  Do not merge copies. -->
   <xsl:template match='control | dynamictext'>
      <xsl:param name="cid" select="@id" />

      <xsl:param name="elName" select="name()" />

      <xsl:param name="mainlang" select="language" />

      <xsl:param name="seclang" select="document('languages_new.xml')//*[name() = $elName][@id = $cid]/language" />

      <xsl:copy>
         <xsl:copy-of select="@*" />

         <xsl:for-each select="$mainlang">
            <xsl:variable name="thisLang" select="." />

            <xsl:copy>
               <xsl:copy-of select="@*" />

               <xsl:copy-of select="value" />

               <xsl:copy-of select="$seclang[@code = $thisLang/@code]/value[not(@text = $thisLang/value/@text)]" />
            </xsl:copy>
         </xsl:for-each>

<!--       <xsl:copy-of select="$mainlang">
         <xsl:copy-of select="$seclang[not(@code = $mainlang/@code)]" />-->
      </xsl:copy>
   </xsl:template>

as you can see i took out the second copy as it was causing the duplications i was getting, only thing it is not doing is adding the missing languages from the new file if the the dynamictext or control already exists.  Also i am using this code in conjunction with the code i wrote above which adds the missing dynamictext or control.
I'll keep playing with the code and see if i can get it to add my missing languages.

Thanks ScotDance
0
 

Author Comment

by:scotdance
ID: 17191033
Hi
Just to let you know i managed to get the code you gave me to work, it turned out all i needed to do was remove the following line:

<xsl:copy-of select="$mainlang" />

but it's been a good learning curve for me trying to figure it all out.

I'm going to try and merge the following two functions i wrote into one now if it is possible.

   <xsl:template match="controls">
      <xsl:param name="ctr" select="." />
      <xsl:param name="sec_ctr" select="document('languages_new.xml')//controls" />
      <xsl:copy>
         <xsl:copy-of select="@*" />
         <xsl:apply-templates select="node() | text()" />
         <xsl:for-each select="$sec_ctr/control[not(@id = $ctr/control/@id)]">
            <xsl:copy-of select="." />
         </xsl:for-each>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="dynamictexts">
      <xsl:param name="dyn" select="." />
      <xsl:param name="sec_dyn" select="document('languages_new.xml')//dynamictexts" />
      <xsl:copy>
         <xsl:copy-of select="@*" />
         <xsl:apply-templates select="node() | text()" />
         <xsl:for-each select="$sec_dyn/dynamictext[not(@id = $dyn/dynamictext/@id)]">
            <xsl:copy-of select="." />
         </xsl:for-each>
      </xsl:copy>
   </xsl:template>

if you got the time can you combine them too so i can see how close i am.

Thanks
ScotDance
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 17233616
ScotDance,

I just returned from holidays,
and will have a look at this later today or tomorrow,

cheers

Geert
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 17234341
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

The Client Need Led Us to RSS I recently had an investment company ask me how they might notify their constituents about their newsworthy publications.  Probably you would think "Facebook" or "Twitter" but this is an interesting client.  Their cons…
I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now