> 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