August 09, 2003
XML Document Construction With Python and libxml2
The libxml Python API is very lightly documented, so this is an attempt to fill in some of the holes that exist.
Creating a new document
To create a new document using the libxml2 API you use a document constructor function that returns an empty document instance. This method takes one argument that repesents the XML version of the document being created.
import libxml2
doc = libxml2.newDoc("1.0")
Creating elements
Once you have a document instance you then need to add elements to it. First off you need to create the root element.
root = doc.newChild(None, "root-element", None)
The root node is created using the xmlDoc.newChild() method. This method takes three parameters.
- namespace - The namespace that the element should belong to or
Noneif no namespace. - node name - The name of the node with no namespace prefix.
- element content - The content for the element or
Noneif the element is empty.
In this particular case we're creating an empty element named root-element. If we were to print this out at this point it would look something like this.
<?xml version="1.0"?> <root-element/>
If we wanted to put the node into a namespace we would write this instead.
root = doc.newChild(None, "root-element", None)
namespace = root.newNs("http://example.com/sample", "sample")
root.setNs(namespace)
The resulting document then becomes.
<?xml version="1.0"?> <sample:root-element xmlns:sample="http://example.com/sample"/>
Now that we've created the root we can continue adding elements to the document. We can add a element child-node in the http://example.com/sample namespace by adding.
child = root.newChild(namespace, "child-node", None)
And our document now looks like
<?xml version="1.0"?>
<sample:root-element xmlns:sample="http://example.com/sample">
<sample:child-node/>
</sample:root-element>
If we had wanted to included some text within the added child it's as simple as just changing the third parameter to newChild.
child = root.newChild(namespace, "child-node", "Some sample text")
Which generates the document
<?xml version="1.0"?>
<sample:root-element xmlns:sample="http://example.com/sample">
<sample:child-node>Some sample text</sample:child-node>
</sample:root-element>
Adding an attribute to an element is also very easy.
child = root.newChild(namespace, "child-node", "Some sample text")
child.setProp("an-attribute", "with a value")
Which of course generates a document that looks like this.
<?xml version="1.0"?>
<sample:root-element xmlns:sample="http://example.com/sample">
<sample:child-node an-attribute="with a value">Some sample text</sample:child-node>
</sample:root-element>
If you wanted the attribute to be part of a namespace, you use setNsProp instead of setProp.
child = root.newChild(namespace, "child-node", "Some sample text") child.setNsProp(namespace, "an-attribute", "with a value")
And the result
<?xml version="1.0"?>
<sample:root-element xmlns:sample="http://example.com/sample">
<sample:child-node sample:an-attribute="with a value">Some sample text</sample:child-node>
</sample:root-element>
Beside simple elements and attributes libxml defines methods to create all the other common XML types. Here's a summary of the methods that are available.
xmlDoc.newDocComment(comment)- Creates a comment node.xmlDoc.newCDataBlock(content, length)- Create a CDATA section.xmlDoc.newDocText(content)- Creates a new text node.
These methods are all node construction methods that are called to create the instance of the required type. Once you have the instance you then need to add it into the document tree where ever you want it. There's also a function available to create processing instructions. This function differs in that it called on the libxml2 module, rather then an xmlDoc instance.
libxml2.newPI (name, content)- Creates a processing instruction
Since these functions require you to create the node and then add it to the document in two steps, libxml provides a number of methods to control where the node is placed in the document tree. These methods are available on any instance of an xmlNode.
xmlNode.addChild(node)- Appends the new node to the list of children for the node.xmlNode.addChildList(nodeList)- Appends a list of new nodes to the children for the node.xmlNode.addNextSibling(node)- Adds the new node as a sibling after the selected node.xmlNode.addPrevSibling(node)- Adds the new node as a sibling before the selected node.xmlNode.addSibling(node)- Adds the new node as a sibling after the selected node. (similar to addNextSibling)xmlNode.addContent(content)- Appends additional text content to an element.
Here's an example that puts everything together.
#!/usr/local/bin/python
import libxml2
doc = libxml2.newDoc("1.0")
root = doc.newChild(None, "root-element", None)
namespace = root.newNs("http://example.com/sample", "sample")
root.setNs(namespace)
child = root.newChild(namespace, "child-node", "Some sample text")
child.setNsProp(namespace, "an-attribute", "with a value")
comment = doc.newDocComment("Just commenting")
child.addPrevSibling(comment)
pi = libxml2.newPI("a-sample-pi", "with some useless content")
root.addPrevSibling(pi)
text = doc.newDocText(" This will be added to the existing text.")
child.addChild(text)
child.addContent(" This will also be added to the text")
print doc.serialize(None, 1)
And a final result.
<?xml version="1.0"?> <?a-sample-pi with some useless content?> <sample:root-element xmlns:sample="http://example.com/sample"> <!--Just commenting--> <sample:child-node sample:an-attribute="with a value">Some sample text This will be added to the existing text. This will also be added to the text</sample:child-node> </sample:root-element>Posted by kstaken at August 9, 2003 07:42 PM | TrackBack
