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 Boris Kolpackov <bo...@codesynthesis.com> on 2009/09/03 09:33:01 UTC
Re: XPath from DOMNode ?
Hi Ben,
Ben Griffin <be...@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
Re: XPath from DOMNode ?
Posted by Ben Griffin <be...@redsnapper.net>.
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 <be...@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