You are viewing a plain text version of this content. The canonical link for it is here.
Posted to c-users@xerces.apache.org by "Hemanth D." <HE...@infosys.com> on 2006/12/01 05:04:48 UTC

Traversing DOM Tree - getNodeValue issue



I have the following code snippet to traverse a NodeList (all element
nodes retrieved using getElementsByTagName). The getNodeName() retrieves
the correct name. However, the getNodeValue() is not printing out the
value. (We have tried dynamic_cast of xNode3 to a DOMElement also but
this also doesn't work. We have also tried using getFirstChild()/
getNextSibling() instead of the below for-loop - but same result. The
NodeName returns the correct value but the NodeValue doesn't)

Can someone please help identifying the problem?

The parser used is XercesDOMParser - parsing a XML using a
MemBufInputSource (rather than a XML file)

    DOMNodeList* xNodeList3   = xNode->getChildNodes();
    const  XMLSize_t ixNodeCount3 = xNodeList3->getLength();

    for (int i3=0; i3<ixNodeCount3; i3++)
    {
        DOMNode* xNode3 = xNodeList3->item(i3);

        if (DOMNode::ELEMENT_NODE == xNode3->getNodeType())
        {
            char* sxNode3Name  =
XMLString::transcode(xNode3->getNodeName());			// OK
            char* sxNode3Value =
XMLString::transcode(xNode3->getNodeValue());			//
retrieves null string

            cout << "Rule: " << (i+1) << "\tNode: " << sxNode3Name <<
"\tValue: " << sxNode3Value<< endl;

            XMLString::release(&sxNode3Name);
            XMLString::release(&sxNode3Value);
        }
    }
    delete xNodeList3;

The XML string used:

	const string sXML = "<?xml version='1.0'?>\
				<kfRuleSet>\
				<kfRule valueType='CONTENT'>\
				<kfStart>11</kfStart>\
				<kfEnd>15</kfEnd>\
				</kfRule>\
				<kfRule valueType='STATIC'>\
				<kfText>-</kfText>\
				</kfRule>\
				</kfRuleSet>";

Actual Output
	Rule: 1	Node:	kfStart	Value:
	Rule: 1	Node:	kfEnd	Value:
	Rule: 2	Node:	kfText	Value:

Expected Output
	Rule: 1	Node:	kfStart	Value: 11
	Rule: 1	Node:	kfEnd	Value: 15
	Rule: 2	Node:	kfText	Value: -



**************** CAUTION - Disclaimer *****************
This e-mail contains PRIVILEGED AND CONFIDENTIAL INFORMATION intended solely for the use of the addressee(s). If you are not the intended recipient, please notify the sender by e-mail and delete the original message. Further, you are not to copy, disclose, or distribute this e-mail or its contents to any other person and any such actions are unlawful. This e-mail may contain viruses. Infosys has taken every reasonable precaution to minimize this risk, but is not liable for any damage you may sustain as a result of any virus in this e-mail. You should carry out your own virus checks before opening the e-mail or attachment. Infosys reserves the right to monitor and review the content of all messages sent to or from this e-mail address. Messages sent to or from this e-mail address may be stored on the Infosys e-mail system.
***INFOSYS******** End of Disclaimer ********INFOSYS***

proper way to use Xerces for what I'm trying to do

Posted by Will Sappington <ws...@ndma.us>.
I'm new to both XML and Xerces, literally starting from scratch.  From
what I've seen in the documentation and some of the posts here, Xerces
provides a lot of capabilities and there may be more than one way to
accomplish a particular task.  I'm trying to make sense of everything
and I have an idea for an approach to the task I've been assigned, but I
have no idea if it's a good approach or even the right way to do it.
I'm hoping that someone here can help me so I don't' spend too much time
going down dead-end paths.

Here's what I'm trying to do.  Some of our applications are configured
with a hierarchical .ini file.  There are 3 levels - application,
section (within an application), and item (within a section).  Users of
the configuration utility class call a method getItem(appID,
sectionName, itemName) to retrieve the value of the requested item.  The
.ini files are pretty standard flat text files with configuration items
specified as name/val pairs.  We'd like to use XML instead of flat .ini
files.  

I've gotten Xerces to build and run with the configuration utility, so
far I can do pretty simple stuff like getElementsByName() and walk node
lists, get their lengths and so on.  I figure I can find a specific item
by walking node lists, but what I'd really like to have is a way of
directly accessing a unique element using its application/section/item
names.  Someone here (my office) asked if I had tried an "xpath", I
don't know what that is, I'm gonna go find out, but I'm concerned that
there may be an approach using XML that is fundamentally different than
how you go about this using a flat file.  That's what I'm looking to
find out first, if there's a general "best" way to do this sort of
thing, and then, whether yes or no, the specifics of how to implement
it.  Any help will be greatly appreciated.

-will


Re: Traversing DOM Tree - getNodeValue issue

Posted by Boris Kolpackov <bo...@codesynthesis.com>.
David Bertoni <db...@apache.org> writes:

> >     DOMNodeList* xNodeList3   = xNode->getChildNodes();
> >     const  XMLSize_t ixNodeCount3 = xNodeList3->getLength();
> >
> >     for (int i3=0; i3<ixNodeCount3; i3++)
>
> You can either iterate through the children, or call
> DOMNode::getTextContent().  My recommendation would be to iterate through
> the children, as getTextContext() will allocate memory that you cannot free
> without destroying the document.

Also using DOMNodeList for iteration over children is probably not
a good idea either: DOMNodeList's item() member function has O(n)
complexity. Accidently I wrote about these two functions in one
of my blog posts:


http://codesynthesis.com/~boris/blog/2006/11/28/xerces-c-dom-potholes/


hth,
-boris

-- 
Boris Kolpackov
Code Synthesis Tools CC
http://www.codesynthesis.com
Open-Source, Cross-Platform C++ XML Data Binding


Re: Traversing DOM Tree - getNodeValue issue

Posted by David Bertoni <db...@apache.org>.
Hemanth D. wrote:
> 
> 
> I have the following code snippet to traverse a NodeList (all element
> nodes retrieved using getElementsByTagName). The getNodeName() retrieves
> the correct name. However, the getNodeValue() is not printing out the
> value. (We have tried dynamic_cast of xNode3 to a DOMElement also but
> this also doesn't work. We have also tried using getFirstChild()/
> getNextSibling() instead of the below for-loop - but same result. The
> NodeName returns the correct value but the NodeValue doesn't)
> 
> Can someone please help identifying the problem?

You need to read a good tutorial on the DOM, so you understand how it works.

> 
> The parser used is XercesDOMParser - parsing a XML using a
> MemBufInputSource (rather than a XML file)
> 
>     DOMNodeList* xNodeList3   = xNode->getChildNodes();
>     const  XMLSize_t ixNodeCount3 = xNodeList3->getLength();
> 
>     for (int i3=0; i3<ixNodeCount3; i3++)
>     {
>         DOMNode* xNode3 = xNodeList3->item(i3);
> 
>         if (DOMNode::ELEMENT_NODE == xNode3->getNodeType())
>         {
>             char* sxNode3Name  =
> XMLString::transcode(xNode3->getNodeName());			// OK
>             char* sxNode3Value =
> XMLString::transcode(xNode3->getNodeValue());			//
> retrieves null string

DOMElemement::getNodeValue() will always return an empty string, because 
the "value" of an element node is in its child(ren).  In your case, the 
text node child.

You can either iterate through the children, or call 
DOMNode::getTextContent().  My recommendation would be to iterate through 
the children, as getTextContext() will allocate memory that you cannot free 
without destroying the document.

Dave