
On 04/12/2012 07:18 AM, Daniel Veillard wrote:
On Tue, Apr 10, 2012 at 01:54:51PM +0200, Juan Hernandez wrote:
Hello,
The code that we use in engine-setup to modify JBoss AS XML configuration files uses the following pattern:
datasourceStr = ''' <datasource ...> ... </datasource> '''
xmlObj.addNodes("//datasource:subsystem/datasource:datasources", datasourceStr)
This looks correct but is in fact generating a incorrect XML document, as the tags being added are not associated to a namespace. The resulting XML file will be correct, but the temporary representation in memory is not. This causes problems if you later, before writing out the modified file, try to use xpath expressions matching the added nodes: there will be no match.
I would suggest that we change the pattern to something like this:
datasourceStr = ''' <any_dummy_tag xmlns="urn:jboss:domain:datasources:1.0"> <datasource ...> ... </datasource> </any_dummy_tag> ''' datasourceNodes = libxml2.parseDoc(datasourceStr).getRootElement().children
xmlObje.addNodes("//datasource:subsystem/datasource:datasources", datasourceNodes)
This way both the representation in memory and the resulting file are correct.
Le me know what you think.
I think it's dangerous to move nodes from one document to another especially if there is namespaces (I assume you're operating in an environment on top of libxml2 as I saw a reference to it ;-)
For libxml2 there is an API in C: http://xmlsoft.org/html/libxml-parser.html#xmlParseInNodeContext which could do what you expect. Maybe there is a binding/wrapper available you could use.
Thanks Daniel, that looks certainly better/easier than what I am proposing. We use libxml2-python, but I can't locate that method there. Do you know if it is possible to use it from python?
Also your "//datasource:subsystem/datasource:datasources" XPath query could lead to multiple result nodes, I would suggest to pick the first result only, I suppose you don't want to add the set of nodes to multiple places
xmlObje.addNodes("(//datasource:subsystem/datasource:datasources)[1]", datasourceNodes)
or something equivalent (unless addNodes() takes care to handle that properly ...)
Yes, the addNodes method takes care of that.