Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Two xml Documents to One!

Posted on 2002-03-08
15
Medium Priority
?
209 Views
Last Modified: 2013-11-19
Hi,

I have an XML document that links to two further XML documents, I need to take the first and run a calculation from a value off the second, and from this produce a third file.

I am iterating through the first using an for-each loop, after opening the document with the document command, writing ourput as I go.

When I come to a point where the identifiying variable is, I am trying to then go into the second XML document to retrieve the data I need, this is where I am struggling.

I am under the impression that I have moved down the tree to the point in XML file 1, then I must go up the tree to the first XML document that links the two files to then enter the second linked document containing the data.

I can't see how I can get data betwwen the two documents.

If anyone understands this can they plz help!

Thanks in advance.
0
Comment
Question by:psilli1
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 10
  • 4
15 Comments
 
LVL 23

Expert Comment

by:b1xml2
ID: 6852346
you can do this via the xslt document function. What parser are you using? You would also have to probably use the node-set function as well.

Post your XML documents (small data sets please) and your expected XML output and also, your XSLT document (i need to know the logic you are using) and we are cooking!
0
 
LVL 23

Expert Comment

by:b1xml2
ID: 6852402
By the way, the best approach is to use XSLT to do the transform.

You could use the appendChild() to append the two documents into the main tree and then run the transform. Trying to do what you are doing using DOM methods alone is a nightmare.
0
 
LVL 1

Author Comment

by:psilli1
ID: 6852471
Hi,

I am using Saxon parser, I seem to have got around the problem but I am not sure if it is a good way or not.  I have created two parameters at the top of the XSLT, one for each of the filenames, now in the main templates of the XSLT i can simply reference which document I need.  It seems to work ok at the moment.

I am very interested though in how the node-set function is used.  I am assuming that it can be used to create a resultant node-set, which can then be parsed to obtain the data.

This is the main xml document, that links the further two together!
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Update SYSTEM "blah.DTD">
<?xml-stylesheet href="blah.xsl" type="text/xsl"?>
<blah>
     <el1 filename="blah.xml"/>
     <el2 filename="blahblah.xml"/>
</blah>

One Data File
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE NFLDivisions SYSTEM "onedata.dtd">
<main>
     <area>
          <Name>North</Name>
          <Team>
               <TeamName>Manchester United</TeamName>
               <League>
                    <Goals>
                         <For>100</For>
                         <Against>94</Against>
                    </Goals>
                    <WLTBreakdown Performance="home">
                         <Won>1</Won>
                         <Lost>0</Lost>
                         <Tied>0</Tied>
                    </WLTBreakdown>
                    <WLTBreakdown Performance="away">
                         <Won>1</Won>
                         <Lost>0</Lost>
                         <Tied>0</Tied>
                    </WLTBreakdown>

.......etc.......


The second xml document contains games.
<Score>
  <Game>
    <Home>
      <Team>Manchester Utd</Team>
      <Result>3</Result>
    </Home>
    <Away>
      <Team>Manchester City</Team>
      <Result>31</Result>
    </Away>
  </Game>
....etc.....

I want to reporoduce the league table with the new results taken into consideration.

Thanks
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 23

Expert Comment

by:b1xml2
ID: 6852486
>>
I am very interested though in how the node-set function is used.  I am assuming that it can be used
to create a resultant node-set, which can then be parsed to obtain the data.

<<
it is used to access a document/node-set created inside a variable
0
 
LVL 23

Expert Comment

by:b1xml2
ID: 6852529
could you provide the structure of the league tables??
0
 
LVL 1

Author Comment

by:psilli1
ID: 6852537
The Structure is the first document!
0
 
LVL 23

Expert Comment

by:b1xml2
ID: 6852563
version of Saxon??? 6.2.2??
0
 
LVL 1

Author Comment

by:psilli1
ID: 6852565
6.5.1
0
 
LVL 23

Expert Comment

by:b1xml2
ID: 6852566
I shall make the presumption that you are using 6.5.1 and will use the node-set function as stated here:

node-set($fragment) When version="1.1", a result-tree-fragment is converted implicitly to a node-set if it is used in a context where a node-set is required. However, for portability with other XSLT 1.0 processors, it may be better to use the EXSLT node-set() function. The function takes a single argument that is a result tree fragment. Its function is to convert the result tree fragment to a node-set. The resulting node-set contains a single node, which is a root node (class DocumentInfo); below this are the actual nodes added to the result tree fragment, which may be element nodes, text nodes, or anything else. Note that a result tree fragment is not in general a well-formed document, for example there may be multiple element nodes or text nodes as children of the root.

http://saxon.sourceforge.net/saxon6.5.1/extensions.html#nodeset
0
 
LVL 23

Expert Comment

by:b1xml2
ID: 6852725
Here is the XML Document, XSLT Document and the final output tested with Saxon 6.5.1


directive.xml
============================

<?xml version="1.0" encoding="iso-8859-1"?>
<document>
    <main filename="data.xml"/>
    <update filename="update.xml"/>
</document>

data.xml
=========
<?xml version="1.0" encoding="iso-8859-1"?>
<main>
<area>
<Name>North</Name>
<Team>
<TeamName>Manchester United</TeamName>
<League>
<Goals>
<For>100</For>
<Against>94</Against>
</Goals>
<WLTBreakdown Performance="home">
<Won>1</Won>
<Lost>0</Lost>
<Tied>0</Tied>
</WLTBreakdown>
<WLTBreakdown Performance="away">
<Won>1</Won>
<Lost>0</Lost>
<Tied>0</Tied>
</WLTBreakdown>
</League>
</Team>
<Team>
<TeamName>Manchester City</TeamName>
<League>
<Goals>
<For>50</For>
<Against>95</Against>
</Goals>
<WLTBreakdown Performance="home">
<Won>0</Won>
<Lost>0</Lost>
<Tied>1</Tied>
</WLTBreakdown>
<WLTBreakdown Performance="away">
<Won>0</Won>
<Lost>1</Lost>
<Tied>0</Tied>
</WLTBreakdown>            
</League>
</Team>
</area>
</main>

update.xml
==========
<?xml version="1.0" encoding="iso-8859-1"?>
<Score>
<Game>
<Home>
<Team>Manchester United</Team>
<Result>3</Result>
</Home>
<Away>
<Team>Manchester City</Team>
<Result>1</Result>
</Away>
</Game>
</Score>


saxon.xsl
=========
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:saxon="http://icl.com/saxon" exclude-result-prefixes="saxon">
<xsl:output method="xml" version="1.0" encoding="iso-8859-1" indent="yes" />
<xsl:variable name="main" select="document(//main/@filename)/main" />
<xsl:variable name="update" select="document(//update/@filename)/score" />
<xsl:template match="/">
<xsl:apply-templates select="saxon:node-set($main)/node()" mode="update" />
</xsl:template>
<xsl:template match="@* | node()" mode="update">
<xsl:copy><xsl:apply-templates select="@* | node()" mode="update" /></xsl:copy>
</xsl:template>

<!--total goals for-->
<xsl:template match="Goals/For" mode="update">
<xsl:variable name="team" select="preceding::TeamName[1]" />
<xsl:variable name="for" select="sum(saxon:node-set($update)//Result[preceding-sibling::Team[1] = $team])" />
<For><xsl:value-of select=". + $for" /></For>
</xsl:template>

<!--total goals against-->
<xsl:template match="Goals/Against" mode="update">
<xsl:variable name="team" select="preceding::TeamName[1]" />
<xsl:variable name="home" select="sum(saxon:node-set($update)//Game[Away/Team[. = $team]]/Home/Result)" />
<xsl:variable name="away" select="sum(saxon:node-set($update)//Game[Home/Team[. = $team]]/Away/Result)" />
<Against><xsl:value-of select=". + $away + $home" /></Against>
</xsl:template>

<!--home details-->
<xsl:template match="WLTBreakdown[@Performance[. = 'home']]" mode="update">
<xsl:variable name="team" select="preceding::TeamName[1]" />
<xsl:variable name="won" select="count(saxon:node-set($update)//Game[Home[Team[. = $team]]/Result &gt; Away/Result])" />
<xsl:variable name="tied" select="count(saxon:node-set($update)//Game[Home[Team[. = $team]]/Result = Away/Result])" />
<xsl:variable name="lost" select="count(saxon:node-set($update)//Game[Home[Team[. = $team]]/Result &lt; Away/Result])" />
<WLTBreakdown Performance="home">
      <Won><xsl:value-of select="Won + $won" /></Won>
      <Lost><xsl:value-of select="Lost + $lost" /></Lost>
      <Tied><xsl:value-of select="Tied + $tied" /></Tied>
</WLTBreakdown>
</xsl:template>

<!--away details-->
<xsl:template match="WLTBreakdown[@Performance[. = 'away']]" mode="update">
<xsl:variable name="team" select="preceding::TeamName[1]" />
<xsl:variable name="won" select="count(saxon:node-set($update)//Game[Away[Team[. = $team]]/Result &gt; Home/Result])" />
<xsl:variable name="tied" select="count(saxon:node-set($update)//Game[Away[Team[. = $team]]/Result = Home/Result])" />
<xsl:variable name="lost" select="count(saxon:node-set($update)//Game[Away[Team[. = $team]]/Result &lt; Home/Result])" />
<WLTBreakdown Performance="away">
      <Won><xsl:value-of select="Won + $won" /></Won>
      <Lost><xsl:value-of select="Lost + $lost" /></Lost>
      <Tied><xsl:value-of select="Tied + $tied" /></Tied>
</WLTBreakdown>
</xsl:template>
</xsl:stylesheet>


for those wondering what is the equivalent in msxml, here is the stylesheet
msxml.xsl
=========
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" version="1.0" encoding="iso-8859-1" indent="yes" />
<xsl:variable name="main" select="document(//main/@filename)" />
<xsl:variable name="update" select="document(//update/@filename)" />
<xsl:template match="/">
<xsl:apply-templates select="msxsl:node-set($main)/node()" mode="update" />
</xsl:template>
<xsl:template match="@* | node()" mode="update">
<xsl:copy><xsl:apply-templates select="@* | node()" mode="update" /></xsl:copy>
</xsl:template>

<!--total goals for-->
<xsl:template match="Goals/For" mode="update">
<xsl:variable name="team" select="preceding::TeamName[1]" />
<xsl:variable name="for" select="sum(msxsl:node-set($update)//Result[preceding-sibling::Team[1] = $team])" />
<For><xsl:value-of select=". + $for" /></For>
</xsl:template>

<!--total goals against-->
<xsl:template match="Goals/Against" mode="update">
<xsl:variable name="team" select="preceding::TeamName[1]" />
<xsl:variable name="home" select="sum(msxsl:node-set($update)//Game[Away/Team[. = $team]]/Home/Result)" />
<xsl:variable name="away" select="sum(msxsl:node-set($update)//Game[Home/Team[. = $team]]/Away/Result)" />
<Against><xsl:value-of select=". + $away + $home" /></Against>
</xsl:template>

<!--home details-->
<xsl:template match="WLTBreakdown[@Performance[. = 'home']]" mode="update">
<xsl:variable name="team" select="preceding::TeamName[1]" />
<xsl:variable name="won" select="count(msxsl:node-set($update)//Game[Home[Team[. = $team]]/Result &gt; Away/Result])" />
<xsl:variable name="tied" select="count(msxsl:node-set($update)//Game[Home[Team[. = $team]]/Result = Away/Result])" />
<xsl:variable name="lost" select="count(msxsl:node-set($update)//Game[Home[Team[. = $team]]/Result &lt; Away/Result])" />
<WLTBreakdown Performance="home">
      <Won><xsl:value-of select="Won + $won" /></Won>
      <Lost><xsl:value-of select="Lost + $lost" /></Lost>
      <Tied><xsl:value-of select="Tied + $tied" /></Tied>
</WLTBreakdown>
</xsl:template>

<!--away details-->
<xsl:template match="WLTBreakdown[@Performance[. = 'away']]" mode="update">
<xsl:variable name="team" select="preceding::TeamName[1]" />
<xsl:variable name="won" select="count(msxsl:node-set($update)//Game[Away[Team[. = $team]]/Result &gt; Home/Result])" />
<xsl:variable name="tied" select="count(msxsl:node-set($update)//Game[Away[Team[. = $team]]/Result = Home/Result])" />
<xsl:variable name="lost" select="count(msxsl:node-set($update)//Game[Away[Team[. = $team]]/Result &lt; Home/Result])" />
<WLTBreakdown Performance="away">
      <Won><xsl:value-of select="Won + $won" /></Won>
      <Lost><xsl:value-of select="Lost + $lost" /></Lost>
      <Tied><xsl:value-of select="Tied + $tied" /></Tied>
</WLTBreakdown>
</xsl:template>

</xsl:stylesheet>

xml output
==========
<?xml version="1.0" encoding="iso-8859-1"?>
<main><area><Name>North</Name>
<Team><TeamName>Manchester United</TeamName>
<League><Goals><For>103</For>
<Against>95</Against>
</Goals>
<WLTBreakdown Performance="home">
<Won>2</Won>
<Lost>0</Lost>
<Tied>0</Tied>
</WLTBreakdown>
<WLTBreakdown Performance="away">
<Won>1</Won>
<Lost>0</Lost>
<Tied>0</Tied>
</WLTBreakdown>
</League>
</Team>
<Team><TeamName>Manchester City</TeamName>
<League><Goals><For>51</For>
<Against>98</Against>
</Goals>
<WLTBreakdown Performance="home">
<Won>0</Won>
<Lost>0</Lost>
<Tied>1</Tied>
</WLTBreakdown>
<WLTBreakdown Performance="away">
<Won>0</Won>
<Lost>2</Lost>
<Tied>0</Tied>
</WLTBreakdown>
</League>
</Team>
</area>
</main>

0
 
LVL 23

Expert Comment

by:b1xml2
ID: 6852734
Notes
=====
1. It is much simpler using the element transformation technique seen here to update the original transform.

2. To see the transform, I used the command line
java -jar saxon.jar "directive.xml" "saxon.xsl" and the output was exactly the same as that for msxml.xsl

3. by using the element transformation technique, we leave untouched elements that we wish to pass thru untouched like TeamName element and area.

4. The templates after
<xsl:template match="@* | node()" mode="update">
<xsl:copy><xsl:apply-templates select="@* | node()" mode="update" /></xsl:copy>
</xsl:template>

targets the elements that we interested in updating.

Regards,

Brandon Driesen
0
 
LVL 23

Accepted Solution

by:
b1xml2 earned 800 total points
ID: 6852756
a slight amendment to the saxon.xsl, i posted the debugged version LOL,

saxon.xsl
=========
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:saxon="http://icl.com/saxon" exclude-result-prefixes="saxon">
<xsl:output method="xml" version="1.0" encoding="iso-8859-1" indent="yes" />
<xsl:variable name="main" select="document(//main/@filename)" />
<xsl:variable name="update" select="document(//update/@filename)" />
<xsl:template match="/">
<xsl:apply-templates select="saxon:node-set($main)/node()" mode="update" />
</xsl:template>
<xsl:template match="@* | node()" mode="update">
<xsl:copy><xsl:apply-templates select="@* | node()" mode="update" /></xsl:copy>
</xsl:template>

<!--total goals for-->
<xsl:template match="Goals/For" mode="update">
<xsl:variable name="team" select="preceding::TeamName[1]" />
<xsl:variable name="for" select="sum(saxon:node-set($update)//Result[preceding-sibling::Team[1] = $team])" />
<For><xsl:value-of select=". + $for" /></For>
</xsl:template>

<!--total goals against-->
<xsl:template match="Goals/Against" mode="update">
<xsl:variable name="team" select="preceding::TeamName[1]" />
<xsl:variable name="home" select="sum(saxon:node-set($update)//Game[Away/Team[. = $team]]/Home/Result)" />
<xsl:variable name="away" select="sum(saxon:node-set($update)//Game[Home/Team[. = $team]]/Away/Result)" />
<Against><xsl:value-of select=". + $away + $home" /></Against>
</xsl:template>

<!--home details-->
<xsl:template match="WLTBreakdown[@Performance[. = 'home']]" mode="update">
<xsl:variable name="team" select="preceding::TeamName[1]" />
<xsl:variable name="won" select="count(saxon:node-set($update)//Game[Home[Team[. = $team]]/Result &gt; Away/Result])" />
<xsl:variable name="tied" select="count(saxon:node-set($update)//Game[Home[Team[. = $team]]/Result = Away/Result])" />
<xsl:variable name="lost" select="count(saxon:node-set($update)//Game[Home[Team[. = $team]]/Result &lt; Away/Result])" />
<WLTBreakdown Performance="home">
     <Won><xsl:value-of select="Won + $won" /></Won>
     <Lost><xsl:value-of select="Lost + $lost" /></Lost>
     <Tied><xsl:value-of select="Tied + $tied" /></Tied>
</WLTBreakdown>
</xsl:template>

<!--away details-->
<xsl:template match="WLTBreakdown[@Performance[. = 'away']]" mode="update">
<xsl:variable name="team" select="preceding::TeamName[1]" />
<xsl:variable name="won" select="count(saxon:node-set($update)//Game[Away[Team[. = $team]]/Result &gt; Home/Result])" />
<xsl:variable name="tied" select="count(saxon:node-set($update)//Game[Away[Team[. = $team]]/Result = Home/Result])" />
<xsl:variable name="lost" select="count(saxon:node-set($update)//Game[Away[Team[. = $team]]/Result &lt; Home/Result])" />
<WLTBreakdown Performance="away">
     <Won><xsl:value-of select="Won + $won" /></Won>
     <Lost><xsl:value-of select="Lost + $lost" /></Lost>
     <Tied><xsl:value-of select="Tied + $tied" /></Tied>
</WLTBreakdown>
</xsl:template>

</xsl:stylesheet>

0
 
LVL 23

Expert Comment

by:b1xml2
ID: 6860059
feedback, please?!
0
 
LVL 1

Author Comment

by:psilli1
ID: 6860304
Sorry, ur code gave me a vgood base as to how to use the node-set command, and from this i have been able to produce the XSL to create the new XML document.

Thanks for ur help!

Also, u may be able to help me on one last thing, I have a comma separated value in one of my elements, is there a way of spliting this then looping throuh the results creating a new element for each?

If not then no problem, and tnx 4 the help.
0
 
LVL 1

Expert Comment

by:vijayneema
ID: 7143341
Hi,

Have a look at this question too.

http://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=xml&qid=20321652

Thanks
vijayneema
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction Knockoutjs (Knockout) is a JavaScript framework (Model View ViewModel or MVVM framework).   The main ideology behind Knockout is to control from JavaScript how a page looks whilst creating an engaging user experience in the least …
SASS allows you to treat your CSS code in a more OOP way. Let's have a look on how you can structure your code in order for it to be easily maintained and reused.
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…
The viewer will receive an overview of the basics of CSS showing inline styles. In the head tags set up your style tags: (CODE) Reference the nav tag and set your properties.: (CODE) Set the reference for the UL element and styles for it to ensu…
Suggested Courses

618 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