Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 562
  • Last Modified:

Merging two XML files into one part 3

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
scotdance
Asked:
scotdance
  • 6
  • 5
1 Solution
 
Geert BormansCommented:
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
 
scotdanceAuthor Commented:
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
 
scotdanceAuthor Commented:
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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
Geert BormansCommented:
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
 
scotdanceAuthor Commented:
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
 
Geert BormansCommented:
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
 
scotdanceAuthor Commented:
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
 
scotdanceAuthor Commented:
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
 
scotdanceAuthor Commented:
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
 
Geert BormansCommented:
ScotDance,

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

cheers

Geert
0
 
Geert BormansCommented:
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 6
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now