xerces-c-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ben Griffin <...@redsnapper.net>
Subject Re: XPath from DOMNode ?
Date Thu, 03 Sep 2009 10:40:29 GMT
Boris thanks for that.
I came to a similar conclusion, which manages the element indices.
Not particularly rocket science - but here it is to share...

I found that basic_ostringstream<XMLCh> doesn't seem to deal well with  
single XMLCh characters or unsigned int, so I wrapped all of those up  
in XMLCh[]

basic_string<XMLCh> Parser::xpath(const DOMNode* startnode) {
	basic_string<XMLCh> xpath;
	if (startnode != NULL) {
		basic_ostringstream<XMLCh> osd;
		XMLCh sibch[8];					//For number conversion.
		const XMLCh sls[]= {'/',chNull};		// "/"
		const XMLCh bkt[]= {'(',')',chNull};	// "()"
		const XMLCh osq[]= {'[',chNull};		// "["
		const XMLCh csq[]= {']',chNull};		// "]"
		vector<basic_string<XMLCh> > bits;
		const DOMNode* n = startnode;
		while ( n != NULL ) {
			basic_ostringstream<XMLCh> oss;
			basic_string<XMLCh> name = n->getNodeName();
			if (name[0] == '#' && n->getNodeType() != DOMNode::DOCUMENT_NODE ) {
					name.erase(0,1); //remove the hash.
					oss << sls << name << bkt;
			} else {
				//This is v.slow for travelling through DOMText - will loop  
through each char.
				unsigned long sibnum = 1;
				const xercesc::DOMNode* s = n->getPreviousSibling();
				while ( s != NULL) {
					if (!name.compare(s->getNodeName())) { sibnum++ ;}
					s = s->getPreviousSibling();
				}
				XMLString::binToText(sibnum,sibch,7,10);
				oss << sls << name << osq << sibch << csq;
			}
			n = n->getParentNode();
			bits.push_back(oss.str());
		}
		while (bits.size() > 0) {
			xpath.append(bits.back());
			bits.pop_back();
		}
	}
	return xpath;
}


Best regards
	Ben.

On 3 Sep 2009, at 08:33, Boris Kolpackov wrote:

> Hi Ben,
>
> Ben Griffin <ben@redsnapper.net> writes:
>
>> Given a specific DOMNode, is there a method for finding (or  
>> deriving) a
>> valid XPath that uniquely identifies that DOMNode?
>
> You could go up the document tree (by calling getParentNode) and  
> construct
> the XPath path by prefixing the element names, something along these
> lines (pseudo-code):
>
> string xpath (DOMElement* n)
> {
>  if (n == 0)
>    return "/";
>  else
>    return xpath (n->getParentNode ()) + "/" + n->getName ();
> }
>
> This will work for documents that don't contain sequences of elements
> on the same lavel. If you have to handle this situation then you will
> need to extend this logic to also include the element indexes, e.g.,
> //foo/bar[2].
>
> Boris
>
> -- 
> Boris Kolpackov, Code Synthesis Tools  http://codesynthesis.com/~boris/blog
> Open-source XML data binding for C++:  http://codesynthesis.com/products/xsd
> XML data binding for embedded systems: http://codesynthesis.com/products/xsde


Mime
View raw message