Link to home
Start Free TrialLog in
Avatar of Matt Grofsky
Matt GrofskyFlag for United States of America

asked on

Parse XML with coldfusion

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>
Avatar of R7AF
R7AF
Flag of Netherlands image

Avatar of Matt Grofsky

ASKER

ya saw this article, it doesnt really show how to drill down into elements to grab data from within sub nodes.
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>
ASKER CERTIFIED SOLUTION
Avatar of Scott Bennett
Scott Bennett
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.
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 =)

Avatar of mkishline
mkishline

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>
Boy, it'd be nice if I double checked the status of a question before posting ;)
well played indeed