[Engine-devel] Issue with XML namespaces in engine-setup

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. Regards, Juan Hernandez -- Dirección Comercial: C/Jose Bardasano Baos, 9, Edif. Gorbea 3, planta 3ºD, 28016 Madrid, Spain Inscrita en el Reg. Mercantil de Madrid – C.I.F. B82657941 - Red Hat S.L.

----- Original Message -----
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.
As long as it work, I have no problem with that, sounds the right thing to do. btw- why would you want to use xpath on the "in memory" xml? (In your specific case I mean, not in general)
Regards, Juan Hernandez -- Dirección Comercial: C/Jose Bardasano Baos, 9, Edif. Gorbea 3, planta 3ºD, 28016 Madrid, Spain Inscrita en el Reg. Mercantil de Madrid – C.I.F. B82657941 - Red Hat S.L. _______________________________________________ Engine-devel mailing list Engine-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-devel

On 04/11/2012 09:51 AM, Ofer Schreiber wrote:
----- Original Message -----
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.
As long as it work, I have no problem with that, sounds the right thing to do. btw- why would you want to use xpath on the "in memory" xml? (In your specific case I mean, not in general)
The specific case is that in the Fedora 17 JBoss AS RPM the default standaonle.xml file doesn't contain a <datasources> tag, so I wanted to do something like this: 1. Check if the datasources tag is there, if not add it. 2. Add the new datasource tag, like we do now. Step 2 fails: the xpath that we use in xmlObj.addNodes doesn't match the datasources tag added in step 1 because the in memory XML is not using the right namespace. -- Dirección Comercial: C/Jose Bardasano Baos, 9, Edif. Gorbea 3, planta 3ºD, 28016 Madrid, Spain Inscrita en el Reg. Mercantil de Madrid – C.I.F. B82657941 - Red Hat S.L.

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. 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 ...) Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

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.

On Fri, Apr 13, 2012 at 07:59:32PM +0200, Juan Hernandez wrote:
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?
Argh, right it's missing :-( the bindings could not be automatically generated. I need to add this but before it's deployed it will take a while, too bad that was the right way to do it :-\ To get back to your original problem, I would suggest to correct explicitely the namespaces on the nodes rather than move them from an external document, this feel less risky. The lxml python bindings around libxml2 [1] try to avoid such issues by making sure all documents share the same dictionary and control the copy operations, but I don't know if Stefan Behnel managed to cover all the cases Daniel [1] http://lxml.de/ -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/
participants (4)
-
Daniel Veillard
-
Juan Hernandez
-
Juan Hernandez
-
Ofer Schreiber