?
Solved

How to loop through xml nodes using javascript

Posted on 2010-01-13
26
Medium Priority
?
968 Views
Last Modified: 2013-11-18
I have created the following line of code:

          if ("<xsl:value-of select='//Pathway/PathwayNo/Item1/matrix/no6/score0'/>" == "red") {
          document.getElementById('optAM1Cell0ID').style.backgroundColor = "#FF0000";
          }else if ("<xsl:value-of select='//Pathway/PathwayNo/Item1/matrix/no6/score0'/>" == "yellow") {
          document.getElementById('optAM1Cell0ID').style.backgroundColor = "#FFFF00";
          }else {
          document.getElementById('optAM1Cell0ID').style.backgroundColor = "#FFFFFF";
          }

          if ("<xsl:value-of select='//Pathway/PathwayNo/Item1/matrix/no6/score1'/>" == "red") {
          document.getElementById('optAM1Cell1ID').style.backgroundColor = "#FF0000";
          }else if ("<xsl:value-of select='//Pathway/PathwayNo/Item1/matrix/no6/score1'/>" == "yellow") {
          document.getElementById('optAM1Cell1ID').style.backgroundColor = "#FFFF00";
          }else {
          document.getElementById('optAM1Cell1ID').style.backgroundColor = "#FFFFFF";
          }

Having a look at the xpath and where it says "score0" and on the second part it says "score1". So basically what I want to do is create a javscript where is loops the same line of code and changes the xpath at the bit where "score" and it adds the number on the end automatically producing score0,score1,score2 using the loop.

Remember this is xpath therefore is needs to pick up the values from the xml file. I need help on the code to do this.
0
Comment
Question by:dipster307
[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
  • 14
  • 6
  • 6
26 Comments
 
LVL 39

Expert Comment

by:abel
ID: 26304223
(please use the code-window for code snippets...)

Ehrm, you're comparing a string, which contains a piece of XSLT, with a string "red". That'll always fail. Where's your XSLT or XPath invocation code? Strings are not magically transformed into executing code.

When you're going to do client-side XSLT or XPath, first things you need to do is load your data as XML. Then you can use the XPath or XSLT functions to go through the nodes. Because this is different per browser, I suggest you have a look at the Sarissa library. It comes with easy-to-follow examples. Try them out and then see if that can help you. Take a few hours or days to learn XPath + XSLT before you really try to attempt it with JavaScript.

See: http://dev.abiss.gr/sarissa/
0
 
LVL 2

Expert Comment

by:smwolke
ID: 26304947
this code will store the values in an array.  you then can loop through the array and split the string to get the key:value pair.
var items = [
                    <xsl:for-each select="//Pathway/PathwayNo/Item1/matrix/no6/child::*[starts-with(local-name(self::node()),'score')]">
                    '<xsl:value-of select="substring-after(local-name(./self::node()), 'score')"/>:<xsl:value-of select="self::node()"/>',
                    </xsl:for-each>];
                    for(x in items){
                        alert(items[x]);
                    }

Open in new window

0
 
LVL 39

Expert Comment

by:abel
ID: 26305615
@smwolke: I'm afraid you cannot mix literal XSLT code and literal JavaScript code just like that... And it doesn't get it executed either...
0
What is a Denial of Service (DoS)?

A DoS is a malicious attempt to prevent the normal operation of a computer system. You may frequently see the terms 'DDoS' (Distributed Denial of Service) and 'DoS' used interchangeably, but there are some subtle differences.

 
LVL 2

Expert Comment

by:smwolke
ID: 26305839
I was assuming that his code excerpt was generating HTML with javascript from a transformation of XML by an XSL document.   For example in the code example first is the xml, second is the xsl.  the result of a transformation is a html with javascript.
<Pathway>
    <PathwayNo>
        <Item1>
            <matrix>
                <no6>
                    <score0>red</score0>
                    <score1>green</score1>
                    <score2>blue</score2>
                    <score3>black</score3>
                    <score12>blue</score12>
                    <score13>black</score13>
                </no6>
            </matrix>
        </Item1>
    </PathwayNo>
</Pathway>


<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="html"/>

    <xsl:template match="/">
        <html>
            <head>
                <title>xpath</title>
                <script>
                    var items = [ 
                    <xsl:for-each select="//Pathway/PathwayNo/Item1/matrix/no6/child::*[starts-with(local-name(self::node()),'score')]"> 
                    '<xsl:value-of select="substring-after(local-name(./self::node()), 'score')"/>:<xsl:value-of select="self::node()"/>', 
                    </xsl:for-each>]; 
                    for(x in items){ 
                        alert(items[x]); 
                    }
                </script>
            </head>
            <body>
                Got Alerts I hope.
            </body>
        </html>
    </xsl:template>

</xsl:stylesheet>

Open in new window

0
 
LVL 39

Expert Comment

by:abel
ID: 26305884
ah, that would make sense. Then the title "using javascript" is actually the reverse: "how to output javascript with XSLT".

Tx for explaining, I really saw this from another angle ;-)
0
 

Author Comment

by:dipster307
ID: 26312085
Yep the comment made by:

ID:26305839Author:smwolkeDate:13/01/10 08:59 AM

is what I am looking for, but now I am trying understand the coding, the array where it the code state "substring-after" and "child::". This looks like advance xpath, which I havent done before any one got useful notes.
0
 

Author Comment

by:dipster307
ID: 26312258
<Pathway>
    <PathwayNo>
        <Item1>
            <matrix>
                <no6>
                    <score0>red</score0>
                    <score1>green</score1>
                    <score2>blue</score2>
                    <score3>black</score3>
                    <score12>blue</score12>
                    <score13>black</score13>
                </no6>
            </matrix>
        </Item1>
        <Item2>
            <matrix>
                <no6>
                    <score0>red</score0>
                    <score1>green</score1>
                    <score2>blue</score2>
                    <score3>black</score3>
                    <score12>blue</score12>
                    <score13>black</score13>
                </no6>
            </matrix>
        </Item2>
    </PathwayNo>
</Pathway>


<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="html"/>

    <xsl:template match="/">
        <html>
            <head>
                <title>xpath</title>
                <script>
                    var items = [
                    <xsl:for-each select="//Pathway/PathwayNo/Item1/matrix/no6/child::*[starts-with(local-name(self::node()),'score')]">
                    '<xsl:value-of select="substring-after(local-name(./self::node()), 'score')"/>:<xsl:value-of select="self::node()"/>',
                    </xsl:for-each>];
                    for(x in items){
                        alert(items[x]);
                    }
                </script>
            </head>
            <body>
                Got Alerts I hope.
            </body>
        </html>
    </xsl:template>

</xsl:stylesheet>


Looking back at the code, I have added more data to the xml, because this is the bit my org. point was. If there are two "Items" (see xml). I need to be able to do something like below:

<xsl:for-each select="//Pathway/PathwayNo/Item[y]/matrix/no6/score[x]>

So looping through the paths without repeat coding over and over again.
0
 
LVL 39

Expert Comment

by:abel
ID: 26312393
Repeat: "please use the code-window for code snippets..."

With that I meant: click the Code-link, paste your code there, so it gets attached to your comment. This makes it more readable and easier to cut and paste and long lines will not be broken anymore.

I'll leave the answering of your last q. to smwolke, as I'm not sure about his code and your request and he knows his code best ;-)
0
 
LVL 2

Expert Comment

by:smwolke
ID: 26313585
For information on the syntax i used see:

http://www.w3.org/TR/1999/REC-xpath-19991116

Regarding your requirement,  the original post did not state that Item1 would have multiple siblings.  This makes the problem a little more difficult and would require more information.  Does Item[y] have unbounded siblings?  Does Score[x] have unbounded siblings?  Is x always sequential? Is y always sequential?  Can no6 have a sibling no5 that needs to be looped over?

Sorry about all the questions but I want to make sure that I am not trying to hit a moving target.
0
 

Author Comment

by:dipster307
ID: 26314105
basically if item7 is selected then it needs to select data from the xml where it matches the node item7. Then it checks the color, so if I select the score 2, it needs to collect the data from the xml to pick up the color, where the node is score2.

so in coding terms:

for (i=0; i<22; i++)  "There are 21 items, ie 21 nodes <Item1>,<Item2>etc.."
{
if (myItem == i) {
 <xsl:for-each select="//Pathway/PathwayNo/Item[i]">
0
 

Author Comment

by:dipster307
ID: 26314107
basically if item7 is selected then it needs to select data from the xml where it matches the node item7. Then it checks the color, so if I select the score 2, it needs to collect the data from the xml to pick up the color, where the node is score2.

so in coding terms:

for (i=0; i<22; i++)  "There are 21 items, ie 21 nodes <Item1>,<Item2>etc.."
{
if (myItem == i) {
 <xsl:for-each select="//Pathway/PathwayNo/Item[i]">
0
 

Author Comment

by:dipster307
ID: 26314108
basically if item7 is selected then it needs to select data from the xml where it matches the node item7. Then it checks the color, so if I select the score 2, it needs to collect the data from the xml to pick up the color, where the node is score2.

so in coding terms:

for (i=0; i<22; i++)  "There are 21 items, ie 21 nodes <Item1>,<Item2>etc.."
{
if (myItem == i) {
 <xsl:for-each select="//Pathway/PathwayNo/Item[i]">
0
 

Author Comment

by:dipster307
ID: 26314149
ignore the last 3 comments it was a mistake as I didnt finish my message.

basically if item7 is selected then it needs to select data from the xml where it matches the node item7. Then it checks the color, so if I select the score 2, it needs to collect the data from the xml to pick up the color, where the node is score2.

so in coding terms see below.


for (i=0; i<22; i++)  "There are 21 items, ie 21 nodes <Item1>,<Item2>etc.."
{
if (myItem == i) {
 <xsl:for-each select="//Pathway/PathwayNo/Item[i]">
for (y=0; y<5; y++) { 
if (myscore == y) {
<xsl:value-of select="matrix/no6/score[y]>
}
}
}

Open in new window

0
 

Author Comment

by:dipster307
ID: 26314389
or the best way to explain is each <Item> node has a child node <name> and you want a alert box to display the names for each <Item> node

<nodetest>
<item1>
<name>testing1</name>
</item1>
<item2>
<name>super2</name>
</item2>
<item3>
<name>cool3</name>
</item3>
</nodetest>

for (i=0; i<4; i++) {
<xsl:value-of select='//Pathway/PathwayNo/Item " + i + "/name'/>
}

this is what I am trying to do, but then within this loop is the score as well like a loop in a loop. The above doesnt work because you cant use xpath in that way?
0
 

Author Comment

by:dipster307
ID: 26314390
or the best way to explain is each <Item> node has a child node <name> and you want a alert box to display the names for each <Item> node

<nodetest>
<item1>
<name>testing1</name>
</item1>
<item2>
<name>super2</name>
</item2>
<item3>
<name>cool3</name>
</item3>
</nodetest>

for (i=0; i<4; i++) {
<xsl:value-of select='//Pathway/PathwayNo/Item " + i + "/name'/>
}

this is what I am trying to do, but then within this loop is the score as well like a loop in a loop. The above doesnt work because you cant use xpath in that way?
0
 

Author Comment

by:dipster307
ID: 26314391
or the best way to explain is each <Item> node has a child node <name> and you want a alert box to display the names for each <Item> node

<nodetest>
<item1>
<name>testing1</name>
</item1>
<item2>
<name>super2</name>
</item2>
<item3>
<name>cool3</name>
</item3>
</nodetest>

for (i=0; i<4; i++) {
<xsl:value-of select='//Pathway/PathwayNo/Item " + i + "/name'/>
}

this is what I am trying to do, but then within this loop is the score as well like a loop in a loop. The above doesnt work because you cant use xpath in that way?
0
 
LVL 39

Expert Comment

by:abel
ID: 26314471
Three times the same comment??? Then again three times the same comment... hmm...
0
 
LVL 2

Expert Comment

by:smwolke
ID: 26315152
Three times is a charm, I guess!

The code above, in your post, will not work because the xpath will be evaluated at the time the transformation takes place and the javascript will be evaluated on the client side.  You could build a multidimensional array to store all values from the nodes for processing when it reaches the client side.  May I ask why you are trying change color on the client side with javascript and not setting it during transformation with a template, which is alot easier?
0
 
LVL 2

Accepted Solution

by:
smwolke earned 1500 total points
ID: 26315691
Something like this is what I meant.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="html"/> 
    <xsl:template match="/"> 
        <html> 
            <head> 
                <title>xpath</title> 
                <script> 
                    var items = [  
                    <xsl:for-each select="//Pathway/PathwayNo/child::*[starts-with(local-name(self::node()),'Item')]">  
                    '<xsl:value-of select="substring-after(local-name(./self::node()), 'Item')"/>',  
                    </xsl:for-each>];  
                    var scores = [  
                    <xsl:for-each select="//Pathway/PathwayNo/child::*[starts-with(local-name(self::node()),'Item')]">  
                    [
                        <xsl:for-each select="//Pathway/PathwayNo/Item1/matrix/no6/child::*[starts-with(local-name(self::node()),'score')]">  
                    '<xsl:value-of select="substring-after(local-name(./self::node()), 'score')"/>:<xsl:value-of select="self::node()"/>',  
                        </xsl:for-each>,
                    ],
                    </xsl:for-each>
                    ];  
                    
                    <![CDATA[
                    <!--
                    var color;
                    var score_num;
                    for(x in items){
                        for(y in scores[x]){
                            score_num = scores[x][y].split(":")[0];
                            color = scores[x][y].split(":")[1];
                            document.write("document.getElementById('optAM" + items[x] + "Cell" + score_num + "ID').style.backgroundColor = " + color);
                            document.write("<br/>");
                        }
                    }
                    -->
                     ]]>
                </script> 
            </head> 
            <body> 
            </body> 
        </html> 
    </xsl:template> 
</xsl:stylesheet>

Open in new window

0
 

Author Comment

by:dipster307
ID: 26358744
I am sure the comment made by "ID:26315691Author:smwolkeDate:14/01/10 08:30 AM", works.

XML:

    <nodetest>
      <item1>
        <name>testing1</name>
        <description>des testing1</description>
      </item1>
      <item2>
        <name>super2</name>
        <description>des super2</description>
      </item2>
      <item3>
        <name>cool3</name>
        <description>des cool3</description>
      </item3>
    </nodetest>


But its a bit to complex, then the one I finally managed to work out.

Firstly read the xml file:

          xmlRead = new ActiveXObject("Microsoft.XMLDOM");
          xmlRead.async=false;
          xmlRead.load("../XML/XMLExample.xml");

Then looping through the xml collecting data, by the user match:

          for (k=1; k<22; k++) {

          if (objMatch1.value==k) {

          xpathItem = xmlRead.getElementsByTagName("Item" + k + "/name");
          for (i=0;i<xpathItem.length;i++) {
          itemDetails = xpathItem[i].lastChild.nodeValue;
          }
          xDocForm.match1PathwayLabelID.value = itemDetails;

          xpathItem = xmlRead.getElementsByTagName("Item" + k + "/description");
          for (i=0;i<xpathItem.length;i++) {
          itemDetails = xpathItem[i].lastChild.nodeValue;
          }
          xDocForm.optADescription.value = itemDetails;
}

This works just fine, and your using up extra memory by creating arrays. What you think "smwolke", works well right????????

0
 

Author Comment

by:dipster307
ID: 26358745
I am sure the comment made by "ID:26315691Author:smwolkeDate:14/01/10 08:30 AM", works.

XML:

    <nodetest>
      <item1>
        <name>testing1</name>
        <description>des testing1</description>
      </item1>
      <item2>
        <name>super2</name>
        <description>des super2</description>
      </item2>
      <item3>
        <name>cool3</name>
        <description>des cool3</description>
      </item3>
    </nodetest>


But its a bit to complex, then the one I finally managed to work out.

Firstly read the xml file:

          xmlRead = new ActiveXObject("Microsoft.XMLDOM");
          xmlRead.async=false;
          xmlRead.load("../XML/XMLExample.xml");

Then looping through the xml collecting data, by the user match:

          for (k=1; k<22; k++) {

          if (objMatch1.value==k) {

          xpathItem = xmlRead.getElementsByTagName("Item" + k + "/name");
          for (i=0;i<xpathItem.length;i++) {
          itemDetails = xpathItem[i].lastChild.nodeValue;
          }
          xDocForm.match1PathwayLabelID.value = itemDetails;

          xpathItem = xmlRead.getElementsByTagName("Item" + k + "/description");
          for (i=0;i<xpathItem.length;i++) {
          itemDetails = xpathItem[i].lastChild.nodeValue;
          }
          xDocForm.optADescription.value = itemDetails;
}

This works just fine, and your using up extra memory by creating arrays. What you think "smwolke", works well right????????

0
 

Author Comment

by:dipster307
ID: 26358746
I am sure the comment made by "ID:26315691Author:smwolkeDate:14/01/10 08:30 AM", works.

XML:

    <nodetest>
      <item1>
        <name>testing1</name>
        <description>des testing1</description>
      </item1>
      <item2>
        <name>super2</name>
        <description>des super2</description>
      </item2>
      <item3>
        <name>cool3</name>
        <description>des cool3</description>
      </item3>
    </nodetest>


But its a bit to complex, then the one I finally managed to work out.

Firstly read the xml file:

          xmlRead = new ActiveXObject("Microsoft.XMLDOM");
          xmlRead.async=false;
          xmlRead.load("../XML/XMLExample.xml");

Then looping through the xml collecting data, by the user match:

          for (k=1; k<22; k++) {

          if (objMatch1.value==k) {

          xpathItem = xmlRead.getElementsByTagName("Item" + k + "/name");
          for (i=0;i<xpathItem.length;i++) {
          itemDetails = xpathItem[i].lastChild.nodeValue;
          }
          xDocForm.match1PathwayLabelID.value = itemDetails;

          xpathItem = xmlRead.getElementsByTagName("Item" + k + "/description");
          for (i=0;i<xpathItem.length;i++) {
          itemDetails = xpathItem[i].lastChild.nodeValue;
          }
          xDocForm.optADescription.value = itemDetails;
}

This works just fine, and your using up extra memory by creating arrays. What you think "smwolke", works well right????????

0
 
LVL 39

Expert Comment

by:abel
ID: 26358789
Just a general question: three times when you posted a comment, you added it three times (totaling 6 doubled comments). Is that on purpose to attract attention? Please try to add comments only once. We will see them, we will get notified so really, one is enough...
0
 
LVL 2

Expert Comment

by:smwolke
ID: 26359552
Regarding the memory usage, I think that if the xslt transformation was done on the server, you would be using less memory with the arrays on the client side.  I say this because your current solution is pulling the whole xml document into a DOM object on the client side and the arrays only were only holding a subset of the xml data.  Your solution assumes that you know the upper limit of the items(k<22) and that the numbers were sequential(i++).  I asked if this were the case but the question was never answered; my solution will cover unknown quantities of bounded items and non sequential items which is why it may seem more complex.  Also your solution not is relevant to xpath.

Just some thoughts.
0
 

Author Comment

by:dipster307
ID: 26359793
thanks for the info from snwolke.

Regarding the posting my comment three times, IT'S NOT ME. I click on sumbit and for strange reason 3 comments are posted, its the website issue, nothing to do with me.
0
 

Author Closing Comment

by:dipster307
ID: 31676610
Didnt state the question clearly, hence why the solution was slightly different to what I was looking for. However the solution does work.
0

Featured Post

Is Your Team Achieving Their Full Potential?

74% of employees feel they are not achieving their full potential. With Linux Academy, not only will you strengthen your team's core competencies but also their knowledge of of the newest IT topics.

With new material every week, we'll make sure that you stay ahead of the game.

Question has a verified solution.

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

Preface This is the third article about the EE Collaborative Login Project. A Better Website Login System (http://www.experts-exchange.com/A_2902.html) introduces the Login System and shows how to implement a login page. The EE Collaborative Logi…
In this article you will learn how to create a free basic website on Bitbucket, a git service provider. Polymer creates dynamic HTML components, which allow more flexibility than static HTML. This tutorial uses Ubuntu Linux but can also be done on W…
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:
Suggested Courses

765 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