• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

ColdFusion and XML - what am I doing incorrectly??

LEGEND ,
Feb 23, 2017 Feb 23, 2017

Copy link to clipboard

Copied

Hello, all,

I've been handed a project - a very simple one - that involves uploading an XML document, parsing the data, and then populating a database with the results.

However, what isn't simple is the XML document.  It's slightly over 3mb in size.

I'm setting a variable with the XML document contents (XmlParse()), and am using (successfully, for the most part) XmlSearch() to get the data.

However, I have run into a bit of a snag; and I'm not having much luck on Google.

The data is for locations around the US - each location has one ID, one Name, one City, one State, one Zip code.  But each location has multiple phone numbers and email addresses.  I'm trying to parse the data in such a way as I can loop through child nodes of the main information and grab only one email address and one phone number.

But no matter what I do, I cannot seem to extract a "length" or structcount of the child nodes that contain the email and phone contact information.  I have tried StructCount(), ArrayLen(), xmlElement.length, and other things to no avail.  Most of the error messages are: "element is undefined in Java object of type class coldfusion.xml.XmlNodeMap referenced as ''"  Huh? 

Anyhoo.. it's almost time to go home, but I'll try to get some code examples up, when I can.

V/r,

^_^

Views

1.3K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Advocate , Feb 24, 2017 Feb 24, 2017

You should be able to do something like StructKeyExists(DATA_ARRAY[idx].g_org_id.list_g_info.g_info, "email_org_id")

Votes

Translate

Translate
LEGEND ,
Feb 24, 2017 Feb 24, 2017

Copy link to clipboard

Copied

Okay.. I have some pseudo-code samples.

Here is a basic XML structure that I'm working with:

<?xml version="1.0" encoding="WINDOWS-1252" ?>
<contact_info>
    <list_g_org_id>
        <g_org_id>
            <org_id1>1000</org_id1>
            <list_g_info>
                <g_info>
                    <country>UNITED STATES</country>
                    ...
                    <pp_org_id>543</pp_org_id>
                    ...
                    <email_org_id>
                        <org_id>
                            <org_idp>234</org_idp>
                            <org_email>
                                <pp_email>
                                    <email_type>Customer Service</email_type>
                                    <email_address>john.doe@this.org</email_address>
                                </pp_email>
                                <pp_email>
                                    <email_type>Distribution</email_type>
                                    <email_address>jane.doe@this.org</email_address>
                                </pp_email>
                                <pp_email>
                                    <email_type>Billing</email_type>
                                    <email_address>jacob.doe@this.org</email_address>
                                </pp_email>
                            </org_email>
                        </org_id>
                    </email_org_id>
                </g_info>
            </list_g_info>
        </g_org_id>
    </list_g_org_id>
    <list_g_org_id>
    ... repeat 1000x
    </list_g_org_id>
</contact_info>

Truncated because it's just too freakin' long, but this is the basic layout.

Now, I set a variable with the XML document object as the value.

thisXML = XmlParse(xmlObj);

DATA_ARRAY = XmlSearch(thisXML,'/contact_info/list_g_org_id');

This can get me most of the information that I need to work with.  I can get the org_id (1000) by using:

DATA_ARRAY[idx].g_org_id.org_id1.XmlText;

DATA_ARRAY[idx].g_org_id.list_g_info.g_info.country.XmlText;

etc and so on..

But when I try to get a length of how many email addresses an org has (it won't always be a set number), I keep getting error messages about something being undefined.  What is the proper CF method of accessing XML node children/information?

V/r,

^_^

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Feb 24, 2017 Feb 24, 2017

Copy link to clipboard

Copied

What code are you using to retrieve the email count?

I assume when you dump it all out you can see it all there?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Feb 24, 2017 Feb 24, 2017

Copy link to clipboard

Copied

Hi, haxtbh​,

What code are you using to retrieve the email count?

I've forgotten all the different things I've tried, but the ones I remember:

EMAIL_count = DATA_ARRAY[idx].g_org_id.list_g_info.g_info.email_org_id.org_id.org_email.length

EMAIL_count = DATA_ARRAY[idx].g_org_id.list_g_info.g_info.email_org_id.org_id.org_email.XmlChildren.length
EMAIL_count = ArrayLen(DATA_ARRAY[idx].g_org_id.list_g_info.g_info.email_org_id.org_id.org_email)
EMAIL_count = StructCount(DATA_ARRAY[idx].g_org_id.list_g_info.g_info.email_org_id.org_id.org_email)
EMAIL_count = ArrayLen(DATA_ARRAY[idx].g_org_id.list_g_info.g_info.email_org_id.org_id.org_email.XmlChildren)
EMAIL_count = StructCount(DATA_ARRAY[idx].g_org_id.list_g_info.g_info.email_org_id.org_id.org_email.XmlChildren)

I assume when you dump it all out you can see it all there?

Yep, yep.

V/r,

^_^

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Feb 24, 2017 Feb 24, 2017

Copy link to clipboard

Copied

I tested your examples and out of them only 2 worked.

  EMAIL_count = ArrayLen(DATA_ARRAY[idx].g_org_id.list_g_info.g_info.email_org_id.org_id.org_email)  ;

  EMAIL_count = ArrayLen(DATA_ARRAY[idx].g_org_id.list_g_info.g_info.email_org_id.org_id.org_email.XmlChildren); 

These even worked if the org_email node was empty.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Feb 24, 2017 Feb 24, 2017

Copy link to clipboard

Copied

This is where using the xmlChildren syntax will help.

If you use: DATA_ARRAY[idx].g_org_id.list_g_info.g_info.email_org_id.org_id.org_email.XMLChildren

You will get an array of child nodes.  You can then use arraylen and other array function on that to get the data and counts.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Feb 24, 2017 Feb 24, 2017

Copy link to clipboard

Copied

Per line 05 of my posted code examples, I've already tried ArrayLen() of the XmlChildren and still get the "element is undefined in Java object of type class coldfusion.xml.XmlNodeMap referenced as ''" error message.  Since I'm assigning the XmlSearch() to the XML, already, could this be screwing things up?

V/r,

^_^

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Feb 24, 2017 Feb 24, 2017

Copy link to clipboard

Copied

I used your exact code and it worked just fine.  What version of CF are you running?  My tests were ran against CF11.  You might want to check the element exists before you try and get the length or wrap it in a try/catch.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Feb 24, 2017 Feb 24, 2017

Copy link to clipboard

Copied

I am running CF 10,0,16,293499 on Tomcat 7.0.54.0 Java 1.8.0_31 and HotFix 16.

I have added a CFDUMP / CFABORT after running the XmlSearch to get DATA_ARRAY, and on the first org record the dump is showing that there are seven XmlChildren (appearing as "xml element") for DATA_ARRAY[idx].g_org_id.list_g_info.g_info.email_org_id.org_id.org_email.

smh.. I appreciate you running my code locally.  Maybe it's because I'm on CF10??

V/r,

^_^

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Feb 24, 2017 Feb 24, 2017

Copy link to clipboard

Copied

Tested this in 10,11 and 2016 and it all seems to be ok.

http://trycf.com/gist/321619630e8f7b5a404e7df787061520/acf11?theme=monokai

Rough gist of it, didnt loop just grabbed the first element of the array.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Feb 24, 2017 Feb 24, 2017

Copy link to clipboard

Copied

*headdesk*  *headdesk*  *headdesk*

I just searched the XML document.  Out of the slightly-more-than 1000 records, not all of them have "email_org_id".  WTF??

Sorry.. we are getting this XML from the customer, who (apparently) doesn't understand what we mean when we ask "Do all orgs within record have all elements, even if empty, in the XML data?"  (As you suggested in #7.)

Which brings me to my next question.. how do I check if the XML element exists before checking for length???  I know how to check CF elements (StructKeyExists(scope,'variable')), but not XML from XmlSearch().

V/r,

^_^

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Feb 24, 2017 Feb 24, 2017

Copy link to clipboard

Copied

You should be able to do something like StructKeyExists(DATA_ARRAY[idx].g_org_id.list_g_info.g_info, "email_org_id")

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Feb 24, 2017 Feb 24, 2017

Copy link to clipboard

Copied

Wasn't sure if StructKeyExists() would work on the XML document object, but apparently it does!  Thank you, haxtbh​.

V/r,

^_^

(Now I just have to get it to loop through those (if they exist) and pick the right one.  Sigh of relief.)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Feb 24, 2017 Feb 24, 2017

Copy link to clipboard

Copied

LATEST

FOLLOW UP:  The customer isn't making this easy.  Not following consistent rules regarding empty values.  Some XML empty values are:

<element_a>

    <type_a></type_a>

    <addr_a></addr_a>

</element_a>

Yet others are:

<element_a/>

      - or -

<element_a>

    <type_a/>

    <addr_a/>

</element_a>

*headdesk*  *headdesk*

V/r,

^_^

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources
Documentation