Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Right or wrong way to search within XML element with XMLSearch?

Given the following XML:

<cfsavecontent variable="xml">
<root>
    <parent>
        <child>I'm the first</child>
        <child>Second</child>
        <child>3rd</child>
    </parent>
    <parent>
        <child>Only child</child>
    </parent>
    <parent>
        <child>I'm 10</child>
        <child>I'm 11!</child>
    </parent>
</root>
</cfsavecontent>

Is this the best way to loop over each parent and then extract all children from that parent?

<cfset xml = XMLParse(Trim(xml))>

<cfset parents = XMLSearch(xml, "//parent")>

<cfloop array="#parents#" index="parent">

    <cfset parent = XMLParse(parent)><!--- Is this needed? --->

    <cfset children = XMLSearch(parent, "//child")>

    <cfloop array="#children#" index="child">
        <cfoutput>#child.XmlText#</cfoutput>
    </cfloop>

</cfloop>

The reason I ask is because I've never been able to extract all child elements from the current XML element.

The 'Is this needed?' comment highlights the line I added to make the proceeding line work. But is it possible to to remove this line and somehow change 'XMLSearch(parent, "//child")' to only get child elements from the current 'parent'?

Thanks.

like image 987
Adrian Lynch Avatar asked Jun 12 '09 12:06

Adrian Lynch


1 Answers

<cfset parent = XMLParse(parent)><!--- Is this needed? --->

No, it's not. It's even a performance penalty because you create a new DOM this way.

You get an array of XML nodes back from XmlSearch() (why else would you use <cfloop array...?). This means these should be equivalent:

<!-- new CF8 syntax -->   
<cfloop array="#parents#" index="parent">
  <cfdump var="#parent#">
</cfloop>

<!-- old syntax -->   
<cfloop from="1" to="#ArrayLen(parents)#" index="i">
  <cfdump var="#parents[i]#">
</cfloop>

To make ColdFusion honor context when searching a node, you need to do:

XMLSearch(parent, ".//child")
-------------------^

If you start an XPath expression with "//", ColdFusion obviously searches the entire document the node belongs to, not just that node's descendants.

But if you are interested in outputting all <child> elements from the document, why not do this instead:

<cfset children = XMLSearch(xml, "//child")>
like image 129
Tomalak Avatar answered Sep 22 '22 15:09

Tomalak