> I'm writing about using XML in C++, and am briefly covering Xerces and 
Xalan. 
> I'd like to show an example of selecting a DOM node using an XPath 
expression 
> and then removing that node from the document. Unfortunately, while I've 
found 
> several ways to use XPath expressions to select a DOM node, they seem to 
return 
> nodes from a read-only view of the document. When I try to do
> 
>         node->getParentNode()->removeChild(node)
> 
> I get an exception stating that the document is non-modifiable.

Yes, the default implementation is read-only, since it's optimized for 
XSLT, which does not allow modification of the source tree.

> Is there a way to do what I'm trying to do using Xalan? If not, what's 
another 
> simple but non-trivial use of Xalan XPath expressions, outside of a 
stylesheet?

This is a pretty common question, and we should probably do a sample to 
illustrate how it's done.  You can search the mailing list archives of 
both xalan-dev and xalan-c-users for "XercesDOMSupport" for more 
information.

The trick is you should use an instance of XercesParserLiaison instead of 
XalanSourceTreeParserLiaison, and an instance of XercesDOMSupport, instead 
of XalanSourceTreeDOMSupport.  Also, you will need to call 
XercesParserLiaison::setBuildWrapperNodes(true) and 
XercesParserLiaison::setBuildMaps(true).  Once you do that, you can call 
XercesParserLiaison::parseXMLStream() and use the returned XalanDocument 
instance as the source tree for evaluating XPath expressions.

To map the resulting XalanNode instance returned from evaluating an XPath 
expression, you first need to recover a pointer to the underlying 
implementation class by calling XercesParserLiaison::
mapDocumentToWrapper().  The implementation class XercesDocumentWrapper 
has some member functions called mapNode() that will map the XalanNode 
instances to their underlying Xerces DOMNode instances.  You can then 
manipulate the Xerces DOM instance as you wish.  However, once you've 
modified the underlying Xerces DOM instance, the existing Xalan wrapper 
will be invalid, and you cannot use either the wrapper or the underlying 
Xerces DOM instance for another XPath evaluation.  If you want to preserve 
the underlying Xerces DOM implementation, you can create it using the 
standard Xerces-C APIs, then simply wrap it using XercesParserLiaison::
createDocument(), rather than using XercesParserLiaison::parseXMLStream().

If it seems complicated, it's meant to be.  Much of the XPath and XSLT 
code assumes the underlying source tree will never be modified, so 
providing a way to wrap the Xerces DOM and allow manipulating it is not 
core functionality and can open up some dangerous holes.  Proceed with 
caution...

Dave

Reply via email to