[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Parse XML with coldfusion

Posted on 2007-08-02
11
Medium Priority
?
902 Views
Last Modified: 2013-12-24
How would I go about parsing a simple XML document in coldfusion.

Lets say the XML document is like

<XMLDATA>
<Order>
<ID>12</ID>
<data1>1</data1>
<data2>2</data2>
<Product>
<Itemname>Shoes</ItemName>
<Itemprice>2.00</Itemprice>
</Product>
<Product>
<Itemname>Socks</ItemName>
<Itemprice>1.00</Itemprice>
</Product>
</Order>
<Order>
<ID>13</ID>
<data1>1</data1>
<data2>2</data2>
<Product>
<Itemname>Shoes</ItemName>
<Itemprice>2.00</Itemprice>
</Product>
<Product>
<Itemname>Socks</ItemName>
<Itemprice>1.00</Itemprice>
</Product>
</Order>
<Order>
<ID>14</ID>
<data1>1</data1>
<data2>2</data2>
<Product>
<Itemname>Shoes</ItemName>
<Itemprice>2.00</Itemprice>
</Product>
<Product>
<Itemname>Socks</ItemName>
<Itemprice>1.00</Itemprice>
</Product>
</Order>
</XMLDATA>
0
Comment
Question by:Matt Grofsky
  • 3
  • 3
  • 3
  • +1
11 Comments
 
LVL 13

Expert Comment

by:R7AF
ID: 19619910
0
 
LVL 13

Expert Comment

by:R7AF
ID: 19619916
0
 
LVL 2

Author Comment

by:Matt Grofsky
ID: 19619926
ya saw this article, it doesnt really show how to drill down into elements to grab data from within sub nodes.
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.

 
LVL 2

Author Comment

by:Matt Grofsky
ID: 19620322
This seems to be the only way I can think of to do it, any other cleaner ways?

<cfset xmlrows = XMLSearch(MyXML,"//XMLDATA") />

<cfloop index="i" from="1" to="#ArrayLen(xmlrows)#">
      <cfloop index="j" from="1" to="#ArrayLen(xmlrows[i].xmlchildren)#">
      #xmlrows[i].xmlchildren[j].XmlName# - #xmlrows[i].xmlchildren[j].XMLText#<BR />
      
      <cfloop index="k" from="1" to="#ArrayLen(xmlrows[i].xmlchildren[j].XmlNodes)#">
      <cfif xmlrows[i].xmlchildren[j].XmlNodes[k].XmlName NEQ "##text">
      Sub Row1: #xmlrows[i].xmlchildren[j].XmlNodes[k].XmlName#: #xmlrows[i].xmlchildren[j].XmlNodes[k].XmlText#<BR />
      
      <cfloop index="L" from="1" to="#ArrayLen(xmlrows[i].xmlchildren[j].XmlNodes[k].XmlNodes)#">
      <cfif xmlrows[i].xmlchildren[j].XmlNodes[k].XmlNodes[L].XmlName NEQ "##text">
      Sub Row2: #xmlrows[i].xmlchildren[j].XmlNodes[k].XmlNodes[L].XmlName#: #xmlrows[i].xmlchildren[j].XmlNodes[k].XmlNodes[L].XmlText#<BR />
      </cfif>
      </cfloop>
0
 
LVL 14

Accepted Solution

by:
Scott Bennett earned 2000 total points
ID: 19620731
It is easier to use xmlSearch and xmlParse to find the nodes you want and loop through them like this:
<cfsavecontent variable="xmlstring"><XMLDATA>
<Order>
      <ID>12</ID>
      <data1>1</data1>
      <data2>2</data2>
      <Product>
            <ItemName>Shoes</ItemName>
            <Itemprice>2.00</Itemprice>
      </Product>
      <Product>
            <ItemName>Socks</ItemName>
            <Itemprice>1.00</Itemprice>
      </Product>
</Order>
<Order>
      <ID>13</ID>
      <data1>1</data1>
      <data2>2</data2>
      <Product>
            <ItemName>Shoes</ItemName>
            <Itemprice>2.00</Itemprice>
      </Product>
      <Product>
            <ItemName>Socks</ItemName>
            <Itemprice>1.00</Itemprice>
      </Product>
</Order>
<Order>
      <ID>14</ID>
      <data1>1</data1>
      <data2>2</data2>
      <Product>
            <ItemName>Shoes</ItemName>
            <Itemprice>2.00</Itemprice>
      </Product>
      <Product>
            <ItemName>Socks</ItemName>
            <Itemprice>1.00</Itemprice>
      </Product>
</Order>
</XMLDATA>
</cfsavecontent>
<cfset xmlOrders = xmlSearch(xmlstring,"XMLDATA/Order")>
<cfoutput>
<cfloop from="1" to="#arraylen(xmlOrders)#" index="i">
      <cfset order = xmlparse(xmlorders[i]).order>
      <hr>
      <b>Order ID</b> #Order.ID.XMLText#<br>
      <b>Order Data1</b> #Order.Data1.XMLText#<br>
      <b>Order Data2</b> #Order.Data2.XMLText#<br>
      <table>
            <tr>
                  <td>Item Name</td>
                  <td>Item Price</td>
            </tr>
      <cfset xmlProducts = xmlSearch(order,"Product")>
      <cfloop from="1" to="#arraylen(xmlProducts)#" index="ii">
            <cfset product = xmlparse(xmlProducts[ii]).Product>
            <tr>
                  <td>#product.ItemName.XMLText#</td>
                  <td>#product.Itemprice.XMLText#</td>
            </tr>
      </cfloop>
      </table>
</cfloop>
</cfoutput>

     
0
 
LVL 2

Author Comment

by:Matt Grofsky
ID: 19620770
ah ok this is what i was looking for to get to that sub node product below order

<cfset order = xmlparse(xmlorders[i]).order>
xmlSearch(order,"Product")>

Thanks.
0
 
LVL 14

Expert Comment

by:Scott Bennett
ID: 19620830
yeah that is the tricky part because the xmlsearch results returns sort of goofy data. I figured that one out by getting frustrated and using something like:
<cfset order = xmlparse(xmlorders[i]).order>
while I was grasping for straws. I didn't think it would really work cause it not "normal" cf syntax but it did, so I was happy. Hopefuly I spared you the hairs I had to pull out of my head =)

0
 
LVL 12

Expert Comment

by:mkishline
ID: 19620930
Unless you're anticipating multiple <xmldata> tags in your xml, you're probably just better off doing:
<cfset xmlrows = XMLSearch(MyXML,"//Order") />

Which will result in one less loop.

Other than that, I can't suggest any changes to your logic, but there is a way to simplify the code so that it's a little more readable. You can assign portions of the xml to variables and then use those variables to dictate the flow of the output:

<cfloop index="i" from="1" to="#ArrayLen(xmlrows)#">
      <cfset row_children = xmlrows[i].xmlchildren />
      <cfloop index="j" from="1" to="#ArrayLen(row_children)#">
            <cfset child_nodes = row_children[j].xmlnodes />
            #row_children[j].xmlname# - #row_children[j].xmltext#<br />
            <cfloop index="k" from="1" to="#ArrayLen(child_nodes)#">
                  <cfset grandchildren = child_nodes[k].xmlnodes />
                  <cfif child_nodes[k].xmlname NEQ '##text'>
                        Sub Row1: #child_nodes[k].xmlname#: #child_nodes[k].xmltext#<br />
                  </cfif>
                  <cfloop index="m" from="1" to="#ArrayLen(grandchildren)#">
                        <cfif grandchildren[m].xmlname NEQ '##text'>
                              Sub Row2: #grandchildren[m].xmlname#: #grandchildren[m].xmltext#<br />
                        </cfif>
                  </cfloop>
            </cfloop>
      </cfloop>
</cfloop>
0
 
LVL 12

Expert Comment

by:mkishline
ID: 19620946
Boy, it'd be nice if I double checked the status of a question before posting ;)
0
 
LVL 14

Expert Comment

by:Scott Bennett
ID: 19621005
lol I gues I beat you this time... that should make up for yesterday
http://www.experts-exchange.com/Web_Development/Software/ColdFusion_Studio/Q_22733092.html =)
0
 
LVL 12

Expert Comment

by:mkishline
ID: 19621027
well played indeed
0

Featured Post

Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

Question has a verified solution.

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

Recently while working on a project I got a very annoying cfdocument has no body error message. I had never seen this error before. So I checked the code. The code was pretty simple; it was Just showing me the cfdocumnt tag and inside that tag a …
Meet the world's only “Transparent Cloud™” from Superb Internet Corporation. Now, you can experience firsthand a cloud platform that consistently outperforms Amazon Web Services (AWS), IBM’s Softlayer, and Microsoft’s Azure when it comes to CPU and …
This Micro Tutorial will teach you how to add a cinematic look to any film or video out there. There are very few simple steps that you will follow to do so. This will be demonstrated using Adobe Premiere Pro CS6.
When cloud platforms entered the scene, users and companies jumped on board to take advantage of the many benefits, like the ability to work and connect with company information from various locations. What many didn't foresee was the increased risk…
Suggested Courses

873 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