473,322 Members | 1,806 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,322 software developers and data experts.

Interesting XML traversing problem

I've been struggling too long with this problem and will revere anyone as a god if they can figure it out.

I have this xml:
Expand|Select|Wrap|Line Numbers
  1. <tasks>
  2.      <task id="t1"/>
  3.      <task id="t2">
  4.           <folderid>one</folderid>
  5.      </task>
  6.      <task id="t3">
  7.           <note>just some content here</note>
  8.           <folderid>two</folderid>
  9.      </task>
  10.      <task id="t4">
  11.           <folderid>two</folderid>
  12.           <folderid>three</folderid>
  13.           <folderid>four</folderid>
  14.      </task>
  15.      <task id="t5">
  16.           <folderid>four</folderid>
  17.      </task>
  18.      <task id="t6"/>
  19.           <note>blah blah blah</note>
  20.      </task>
  21.      <task id="t7"/>
  22. </tasks>
  23.  
And I want this result html:
Expand|Select|Wrap|Line Numbers
  1. <div id="root">
  2.      task t1
  3.      task t6 - blah blah blah
  4.      task t7
  5. </div>
  6. <div id="one">
  7.      task t2
  8. </div>
  9. <div id="two">
  10.      task t3 - just some content here
  11.      task t4
  12. </div>
  13. <div id="three">
  14.      task t4
  15. </div>
  16. <div id="four">
  17.      task t4
  18.      task t5
  19. </div>
  20.  
- each task may have 0 to many "folderid" elements
- each folder id will have it's own div
- each div section will list those tasks that have that folderid
- if a task has no folderid sibling, it is put into the "root" div
- each task can only have one note child element
Oct 14 '08 #1
8 1741
Dormilich
8,658 Expert Mod 8TB
- each task may have 0 to many "folderid" elements
- each folder id will have it's own div
- each div section will list those tasks that have that folderid
- if a task has no folderid sibling, it is put into the "root" div
- each task can only have one note child element
problem 1: your xml is not well-formed (missing root element and xml declaration)
problem 2: please use code tags [code] when posting code

the last requirement will need a DTD or similar for validation (though you could catch such an exception)

the most complicated thing is to get the <div>s right. my proposal - get all <folderid>s (<xsl:for-each>), sort them (<xsl:sort>) and create a new <div> when the content changes.

if you show me what you've done so far, I will gladly re- and advise you.

regards
Oct 14 '08 #2
jkmyoung
2,057 Expert 2GB
Tasks without folder children:
task/[not(folderid)]

Assuming you're using XSLT 1.0 and you have a task template already:
to get the other tasks, you'll probably use something like Muenchian Grouping:
http://www.jenitennison.com/xslt/gro...muenchian.html

Expand|Select|Wrap|Line Numbers
  1. <div id="root">
  2.   <xsl:apply-templates select="task/[not(folderid)]"/>
  3.   <xsl:for-each select="//folderid[not(current() = preceding::folderid]">
  4.   <!-- now you have unique folderids -->
  5.     <div id="{.}">
  6.       <xsl:apply-templates select="//folderid[current() = .]/.."/>
  7.        <!-- get parent task node -->
  8.     </div>
  9.   </xsl:for-each>
  10. </div>
  11.  
Oct 14 '08 #3
Sorry it took so long to get reply. Been a long day at work.

I left the root element and xml declaration out by mistake. I thought it would be easier to ask for help by dummying down the XML. In order to show what I've done so far, I'll post the code as-is.

My XML:
Expand|Select|Wrap|Line Numbers
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <?xml-stylesheet type="text/xsl" href="..\myxsl.xsl"?>
  3. <root version="3">
  4.     <context>
  5.         <folders>
  6.             <folder id="970f67719995f688" name="Inbox" icon="inbox"/>
  7.             <folder id="3a6bd2e5fe4b7b0a" name="Personal" icon="home">
  8.                             <folder id="492e514a76b05a3a" name="Longterm" icon="person"/>
  9.             </folder>
  10.             <folder id="2dab99b095a73877" name="Office" icon="office"/>
  11.             <folder id="734059758a6a0f83" name="Groceries" icon="cart">
  12.                             <folder id="129e2ed6cd372e1f" name="Drinks" icon="cart"/>
  13.                             <folder id="a485f0318e18e0e3" name="Party" icon="music"/>
  14.             </folder>
  15.             <folder id="6c74b7b4eceb796f" name="Very-Important" icon="info"/>
  16.             <folder id="826ceb631b4e7039" name="Web"/>
  17.             <folder id="8c32ad3f8a34db4c" name="XMas"/>
  18.         </folders>
  19.         <tasks>
  20.                 <task id="9cda311cb7351fff" desc="remember the milk"/>
  21.                 <task id="c82f392f4f21dc56" desc="focus on everything"/>
  22.                 <task id="1873b622ff99598f" desc="call Susan">
  23.                                 <folder>3a6bd2e5fe4b7b0a</folder>
  24.                 </task>
  25.                 <task id="0955b7d4fa5b9dfd" desc="research options for participating in north pole expedition">
  26.                                 <note>(before it&apos;'s too late! ;)</note>
  27.                                 <folder>492e514a76b05a3a</folder>
  28.                 </task>
  29.                 <task id="db947856a257c6cf" desc="email Frank (gym thing)">
  30.                                 <folder>970f67719995f688</folder>
  31.                 </task>
  32.                 <task id="4c69ff58577cb622" desc="think about my long-term prospects at ACME">
  33.                                 <folder>2dab99b095a73877</folder>
  34.                 </task>
  35.                 <task id="9699da44e2d7439d" desc="tell Lumbergh what I really think of him">
  36.                                 <folder>2dab99b095a73877</folder>
  37.                 </task>
  38.                 <task id="b0caf9f07c206c69" desc="demolish that HP printer!!!!">
  39.                                 <folder>2dab99b095a73877</folder>
  40.                                 <folder>6c74b7b4eceb796f</folder>
  41.                 </task>
  42.                 <task id="afe68a1c545b9172" desc="buy cheese">
  43.                                 <folder>734059758a6a0f83</folder>
  44.                 </task>
  45.                 <task id="04e9ecce043c46b1" desc="buy spam">
  46.                                 <folder>734059758a6a0f83</folder>
  47.                 </task>
  48.                 <task id="301126e402623bb0" desc="buy lettuce for Susan">
  49.                                 <folder>734059758a6a0f83</folder>
  50.                 </task>
  51.                 <task id="5ab1e5e579a0f7c7" desc="buy this German beer Frank was talking about">
  52.                                 <note>think it was called &quot;"Tannenzäpfle&quot;"</note>
  53.                                 <folder>129e2ed6cd372e1f</folder>
  54.                 </task>
  55.                 <task id="73e4a64f7845856a" desc="buy finger-food">
  56.                                 <folder>a485f0318e18e0e3</folder>
  57.                 </task>
  58.                 <task id="26af69c4e916321e" desc="book flight to Tonga">
  59.                                 <folder>3a6bd2e5fe4b7b0a</folder>
  60.                                 <folder>8c32ad3f8a34db4c</folder>
  61.                 </task>
  62.                 <task id="c43bfd24bd5817af" desc="sign up for lis.to newsletter">
  63.                                 <note>http://lis.to/</note>
  64.                                 <folder>970f67719995f688</folder>
  65.                 </task>
  66.  
  67.             </tasks>
  68.     </context>
  69. </root>
  70.  
My XSL:
Expand|Select|Wrap|Line Numbers
  1. <?xml version="1.0"?>
  2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  3. <xsl:template match="/root/context">
  4. <html>
  5.     <head>
  6.         <title>My Lists</title>
  7.  
  8.     </head>
  9.     <body>
  10.  
  11.     <!-- build divs -->
  12.  
  13.         <div class="tabs-container">
  14.             <xsl:for-each select="//folders//*">
  15.                 <xsl:call-template name="GetTasksByFolderTest">
  16.                                 <xsl:with-param name="FolderId" select="@id"/>
  17.                 </xsl:call-template>
  18.             </xsl:for-each>
  19.             <!--Below is an example of html div's I want-->
  20.             <!--<div class="tab" id="tab1">
  21.                 <h2>number 1</h2>
  22.                 <p>put some crap here</p>
  23.             </div>
  24.             <div class="tab" id="tab2">
  25.                 <h2>number 2</h2>
  26.                 <p>put some crap here too</p>
  27.             </div>
  28.             <div class="tab" id="tab3">
  29.                 <h2>number 3</h2>
  30.                 <p>and more here for tab 3</p>
  31.             </div>
  32.             <div class="tab" id="tab4">
  33.                 <h2>number 4</h2>
  34.                 <p>and yeah put something here for 4</p>
  35.             </div>
  36.             <div class="tab" id="test">
  37.                 <h2>number test</h2>
  38.                 <p>and yeah put something here for test</p>
  39.             </div>-->
  40.         </div><!-- end divs -->
  41.     </body>
  42. </html>
  43. </xsl:template>
  44.  
  45.  
  46. <xsl:template name="GetTasksByFolderTest">
  47. <xsl:param name="FolderId"/>
  48. <xsl:for-each select="//tasks//*">
  49.     <xsl:choose>
  50.         <xsl:when test="$FolderId = @id">
  51.             <xsl:value-of select="@desc"/>
  52.         </xsl:when>
  53.     </xsl:choose>
  54. </xsl:for-each>
  55.     <div class="tab" id="{$FolderId}">
  56.         <h2>
  57.             <xsl:value-of select="$FolderId"/> | <xsl:value-of select="@id"/>
  58.         </h2>            
  59.     </div>
  60. </xsl:template>
  61. </xsl:stylesheet>
  62.  
I can't really change the XML as it's coming from a third-party.


----------------
problem 1: your xml is not well-formed (missing root element and xml declaration)
problem 2: please use code tags [code] when posting code

the last requirement will need a DTD or similar for validation (though you could catch such an exception)

the most complicated thing is to get the <div>s right. my proposal - get all <folderid>s (<xsl:for-each>), sort them (<xsl:sort>) and create a new <div> when the content changes.

if you show me what you've done so far, I will gladly re- and advise you.

regards
Oct 15 '08 #4
I am playing around with this code but can't quite seem to get it to work.

I put it in my Task template and using Cooktop xml I get the error "Keyword xsl:apply-template may not be used here."

Not being very well versed in XSLT, I find reading this code a bit difficult. :(
I'll keep playing around and see if I can eventually figure out how it works.

Thanks.

-------
Tasks without folder children:
task/[not(folderid)]

Assuming you're using XSLT 1.0 and you have a task template already:
to get the other tasks, you'll probably use something like Muenchian Grouping:
http://www.jenitennison.com/xslt/gro...muenchian.html

Expand|Select|Wrap|Line Numbers
  1. <div id="root">
  2.   <xsl:apply-template select="task/[not(folderid)]"/>
  3.   <xsl:for-each select="//folderid[not(current() = preceding::folderid]">
  4.   <!-- now you have unique folderids -->
  5.     <div id="{.}">
  6.       <xsl:apply-templates select="//folderid[current() = .]/.."/>
  7.        <!-- get parent task node -->
  8.     </div>
  9.   </xsl:for-each>
  10. </div>
  11.  
Oct 15 '08 #5
Dormilich
8,658 Expert Mod 8TB
got some basic code working:
Expand|Select|Wrap|Line Numbers
  1. <?xml version="1.0" encoding="ISO-8859-1" ?> 
  2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  3.  
  4. <xsl:output method="html" indent="yes"/>
  5.  
  6. <xsl:template match="/">
  7. <html>
  8. <body>
  9. // I don't know why but apply-templates doesn't get all
  10.     <xsl:for-each select="//folder[@id]">
  11.         <div id="{@id}">
  12.             <xsl:call-template name="xyz"/>
  13.         </div>
  14.     </xsl:for-each>
  15. </body>
  16. </html>
  17. </xsl:template>
  18.  
  19. <xsl:template name="xyz">
  20.     <xsl:variable name="id" select="@id"/>
  21.     <xsl:for-each select="//task[folder = $id]">
  22. task: <xsl:value-of select="@id"/>,
  23. // or whatever code comes here
  24.     </xsl:for-each>
  25. </xsl:template>
  26.  
  27. </xsl:stylesheet>
I skipped the "root" div and the check for the <note> child, but it makes the divs as wanted.

regards

Am I a god now? *gg*
Oct 15 '08 #6
jkmyoung
2,057 Expert 2GB
Accidentally deleted the 's' when posting from apply-templates
Oct 15 '08 #7
Beautiful! Yes, you are a god. Honestly I don't know how some of you XSLT gurus got to where you are. It's a heck of a language to learn.

I added the extra bits of code I needed and got it working exactly as envisioned.

Thank you so much!!!



got some basic code working:
Expand|Select|Wrap|Line Numbers
  1. <?xml version="1.0" encoding="ISO-8859-1" ?> 
  2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  3.  
  4. <xsl:output method="html" indent="yes"/>
  5.  
  6. <xsl:template match="/">
  7. <html>
  8. <body>
  9. // I don't know why but apply-templates doesn't get all
  10.     <xsl:for-each select="//folder[@id]">
  11.         <div id="{@id}">
  12.             <xsl:call-template name="xyz"/>
  13.         </div>
  14.     </xsl:for-each>
  15. </body>
  16. </html>
  17. </xsl:template>
  18.  
  19. <xsl:template name="xyz">
  20.     <xsl:variable name="id" select="@id"/>
  21.     <xsl:for-each select="//task[folder = $id]">
  22. task: <xsl:value-of select="@id"/>,
  23. // or whatever code comes here
  24.     </xsl:for-each>
  25. </xsl:template>
  26.  
  27. </xsl:stylesheet>
I skipped the "root" div and the check for the <note> child, but it makes the divs as wanted.

regards

Am I a god now? *gg*
Oct 16 '08 #8
Dormilich
8,658 Expert Mod 8TB
Beautiful! Yes, you are a god. Honestly I don't know how some of you XSLT gurus got to where you are. It's a heck of a language to learn.
we got there by exercise. for me it was working on my website which uses an awful lot of xml (because I'm too lazy to write static html includes) and somehow the xml has to be displayed as html....

I don't find xsl complicated to learn since you have the standard loop and condition constucts like every other programming lanuage. for me the most difficult part (still) is getting the XPath expressions right (... I need to spend more time at my xsl article, *sigh* ...)

btw. your actual xml was much easier to use than your simplified sample

regards

and don't give up

your personal xsl deity
Oct 16 '08 #9

Sign in to post your reply or Sign up for a free account.

Similar topics

2
by: Jim Cobban | last post by:
I am using Xerces to read an XML file and load it into a DOM so I can update it and subsequently serialize the updated DOM. The problem I have is that as I traverse the DOM I would like to inform...
3
by: Plamen Valtchev | last post by:
This is my problem: From JavaScript I want to find the list of all defined/loaded JavaScript functions/objects/names within the current scope (html page in a browser). the page could contain...
1
by: alfred | last post by:
Hi my question is on traversing a tree with DOM. how would I be able to traverse 2 trees at the same time. I have 2 XML documents, with similar nodes. I would like to traverse 1 xml document,...
4
by: plmanikandan | last post by:
Hi, I am new to link list programming.I need to traverse from the end of link list.Is there any way to find the end of link list without traversing from start(i.e traversing from first to find the...
4
by: A_StClaire_ | last post by:
hi all, I'm trying to implement Huffman coding on letters of a string. I've written functions to define the initial leaf nodes (letters and their frequencies) and to sort them. I've also put...
4
by: Christian Rühl | last post by:
Good Day, folks! I'm having a problem traversing an XmlDocument tree in C#. I only want to access the InnerText of the leafs and the names of their ancestors and show them in a richTextBox. But...
3
joppe
by: joppe | last post by:
Hi! This is probably a stupid question, but I've searched and tried to find the answear for 4 hours now and im getting a little tired. Okay here it goes. I got a list containing a char *data...
30
by: asit | last post by:
We kno that data can be pushed onto the stack or popped 4m it. Can stack be traversed ??
1
by: somcool | last post by:
I am facing an error while traversing a query in MS Access Details - When I click a button, a form which has the query opens up. There are certain fields which are in the form of combo box in the...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.