Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams <Error>Invalid patient name</Error> <Error>PATIENT NOT FOUND</Error> <Message>Incoming MESSAGE DATA 1</Message> </MessageError> <MessageError> <BookingID>456</BookingID> <Error>Undefined patient account number.</Error> <Error>Undefined Account Number</Error> <Message>Incoming MESSAGE DATA 2</Message> </MessageError> <MessageError> <BookingID>789</BookingID> <Error>DOB invalid</Error> <Message>Incoming MESSAGE DATA 3</Message> </MessageError> </root>

My tcl Script:

        set dom [dom parse $msg]
        set root [$dom documentElement]         
        set MessageError [$root selectNodes "/root/msg/MessageError" ]
        foreach node $MessageError {
            set Error [$root selectNodes {/root/msg/MessageError/Error} ]
            #set bookingid [$MessageError text]
            #echo "BookingIDXML - $bookingid"
            #set message [$MessageError text]
            #echo "MessageXML - $message"
            foreach errornode $Error {
                set error [$errornode text]
                echo "ErrorXML - $error"

My output:

ErrorXML - Invalid patient name
ErrorXML - PATIENT NOT FOUND
ErrorXML - Undefined patient account number.
ErrorXML - Undefined Account Number
ErrorXML - DOB invalid
ErrorXML - Invalid patient name
ErrorXML - PATIENT NOT FOUND
ErrorXML - Undefined patient account number.
ErrorXML - Undefined Account Number
ErrorXML - DOB invalid
ErrorXML - Invalid patient name
ErrorXML - PATIENT NOT FOUND
ErrorXML - Undefined patient account number.
ErrorXML - Undefined Account Number
ErrorXML - DOB invalid

There is lack of documentation in the internet with this powerful tool. How do I get an output of? The commented '#' sections of my code doesn't work.

BookingIDXML - 123
ErrorXML - Invalid patient name
MessageXML - Incoming MESSAGE DATA 1
BookingIDXML - 123
ErrorXML - PATIENT NOT FOUND
MessageXML - Incoming MESSAGE DATA 1
BookingIDXML - 456
ErrorXML - Undefined patient account number.
MessageXML - Incoming MESSAGE DATA 2
BookingIDXML - 465
ErrorXML - Undefined Account Number
MessageXML - Incoming MESSAGE DATA 2
BookingIDXML - 789
ErrorXML - DOB invalid
MessageXML - Incoming MESSAGE DATA 3

Thanks in Advance.

The selectNodes method uses XPath (which is very well documented) to find the results to return, with the context node being the object on which you invoke the method. Thus, to find the Error nodes for a particular MessageError, you have to start at the right point. In particular, you probably want the code to do something like this:

foreach messageError [$root selectNodes "/root/msg/MessageError"] {
    # Print some general info (to separate error groups)
    set bookingID [lindex [$messageError selectNodes "BookingID"] 0]
    puts "ID: [$bookingID text]"
    set message [lindex [$messageError selectNodes "Message"] 0]
    puts "Message: [$message text]"
    # Print the errors
    foreach error [$messageError selectNodes "Error"] {
        puts "Error: [$error text]"

If you prefer, you could use ./Error instead of Error as the XPath search term; the effect would be the same but it looks a bit more like a path. What you shouldn't do is start over the search from the root of the document (as /root/msg/MessageError/Error would do) because then you find everything that matches that path, and not just the bits that are within the current sub-context. (Think of the sub-context a bit like the current directory in a filesystem, and the elements as being a little bit like directories; it's a partial analogy — DOM trees aren't directories — but it's still a bit analogous.)

Thank you so much Donal. I'm a total novice with tDOM and XML parsing. Your explanation is very detailed. I understand now and see my mistake. Its a bit scary that your code WORKED on the 1st go. I'm going to read up on XPath. – alsnow Apr 26, 2013 at 13:03 @user I've used tDOM and XPath a few times; that pattern (using foreach to go over the list of nodes found) is so much easier than clawing over the DOM tree manually. (That's also true in every single language that uses the DOM. Seriously, if you're working with DOM then learn at least the basic parts of XPath. I'm glad I did!) – Donal Fellows Apr 28, 2013 at 18:01

You have to reference the $errornode DOM nodes in your code, e.g.:

        foreach errornode $Error {
            set bookingid [[$errornode selectNodes "../BookingID"] text]
            set error [$errornode text]
            set message [[$errornode selectNodes "../Message"] text]
            puts "BookingIDXML - $bookingid"
            puts "ErrorXML - $error"
            puts "MessageXML - $message"
            puts ""

But be aware: The selectNodes method will return a list when more than one node matches the query (e.g. $errornode selectNodes "../Message"). If that's the case you have to use the text method with each single list element.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.