This tutorial is based on the Libxml Tutorial by John Fleck ( ©2002, 2003 ), converted for BlitzMax by Bruce Henderson
Libxml is a BlitzMax library implementing functions for reading, creating and manipulating XML data. This tutorial provides example code and explanations of its basic functionality.
This tutorial is not meant to substitute for that complete documentation, but to illustrate the functions needed to use the library to perform basic operations.
The tutorial is based on a simple XML application, the format includes metadata and the body of the article.
The example code in this tutorial demonstrates how to:
Full code for the examples is included in the appendices.
Libxml declares a number of data types we will encounter repeatedly, hiding the messy stuff so you do not have to deal with it unless you have some specific need.
Parsing the file requires only the name of the file and a single function call, plus error checking. Full code: Appendix B, Code for Keyword Example
Local doc:TxmlDoc
Local node:TxmlNode
doc = TxmlDoc.parseFile(docname)
If doc = Null Then Print "Document not parsed successfully." Return End If
node = doc.GetRootElement()
If node = Null Then Print "empty document" doc.free() Return End If
If node.getName() = "storyinfo" Then parseStory(doc, node) End If
Declare the variable that will refer to your parsed document.
Declare a node variable (you'll need this in order to
interact with individual nodes).
Check to see that the document was successfully parsed. If it
was not, libxml will at this point register an error and stop.
Retrieve the document's root element.
Check to make sure the document actually contains something.
In our case, we need to make sure the document is the right
type. "story" is the root type of the documents used in this tutorial.
Retrieving the content of an element involves traversing the document tree until you find what you are looking for. In this case, we are looking for an element called "keyword" contained within element called "story". The process to find the node we are interested in involves tediously walking the tree. We assume you already have an TxmlDoc called doc and an TxmlNode called node.
Local nodeList:TList = node.getChildren()
Foreach node = EachIn nodeList If node.getName() = "storyinfo" Then parseStory(doc, cur) End If Next
Get list of the child nodes of node. At this
point, node points at the document root, which is
the element "story".
This loop iterates through the elements that are children of
"story", looking for one called "storyinfo". That
is the element that will contain the "keywords" we are
looking for. Once found, it calls the function parseStory.
Function parseStory(doc:TxmlDoc, node:TxmlNode) Local key:StringLocal children:TList = node.getChildren()
For node = EachIn children If node.getName() = "keyword" Then
key = node.getText() Print "keyword: " + key End If Next Return End Function
Again we get thelist of child nodes.
Like the loop above, we then iterate through the nodes, looking
for one that matches the element we're interested in, in this case
"keyword".
When we find the "keyword" element, we need to print
its contents. Remember that in XML, the text
contained within an element is a child node of that element, so we
turn to node.getText() to retrieve it, which iterates through the child nodes returning all text elements. In this case, we just print it out.
XPath allows searching through a document for nodes that match specified criteria. In the example below we search through a document for the contents of all keyword elements.
![]() |
Note |
---|---|
A full discussion of XPath is beyond the scope of this document. For details on its use, see the XPath specification. |
Full code for this example is at Appendix C, Code for XPath Example.
Using XPath requires setting up an xmlXPathContext and then supplying the XPath expression and the context to the xmlXPathEvalExpression function. The function returns an xmlXPathObjectPtr, which includes the set of nodes satisfying the XPath expression.
Function getnodeset:TxmlXPathObject(doc:TxmlDoc, xpath:String)Local context:TxmlXPathContext Local result:TxmlXPathObject
context = doc.newXPathContext()
result = context.evalExpression(xpath)
If result.nodeSetIsEmpty() Then result.free() Print "No result" Return Null
First we declare our variables.
Initialize the context variable.
Check the result and free the memory allocated to result if no result is found.
The TxmlXPathObject returned by the function contains a set of nodes and other information needed to iterate through the set and act on the results. For this example, our function returns the TxmlXPathObject. We use it to print the contents of keyword nodes in our document. The node set object includes the number of elements in the set (getNodeCount()) and an array of nodes (getNodeList()):
For Local node:TxmlNode = EachIn nodeset.getNodeList()
Local keyword:String = node.getText() Print "keyword: " + keyword Next
Here we use getNodeList() to iterate through the array of nodes.
Here we print the contents of each of the nodes returned.
![]() |
Note |
---|---|
Note that we are printing the child node of the node that is returned, because the contents of the keyword element are a child text node. |
The main difference in this example is in parseStory:
Function parseStory (node:TxmlNode, keyword:String)node.addTextChild("keyword", Null, keyword) End Function
The addTextChild method adds a new child element at the
current node's location in the
tree, specified by cur.
Once the node has been added, we would like to write the document to the console. If you want the element to have a namespace, you can add it here as well. In our case, the namespace is Null.
doc.saveFormatFile("-", True)
The first parameter is the name of the file to be written. You'll notice it is "-". In this case, we are specifying we want to display the contents of the file on the console, rather than write it out to an actual physical file. Setting the second parameter to True ensures indenting on output.
Writing an attribute is similar to writing text to a new element. In this case, we'll add a reference URI to our document. Full code: Appendix E, Code for Add Attribute Example.
A reference is a child of the story element, so finding the place to put our new element and attribute is simple. As soon as we do the error-checking test in our parseDoc, we are in the right spot to add our element. But before we do that, we need to make a declaration using a data type we have not seen yet:
Local newattr:TxmlAttribute
We also need an extra TxmlNode:
Local newnode:TxmlNode
The rest of parseDoc is the same as before until we check to see if our root element is story. If it is, then we know we are at the right spot to add our element:
newnode = node.addTextChild("reference", Null, Null)
newattr = newnode.addAttribute("uri", uri)
First we add a new node at the location of the current node
pointer, node, using the addTextChild function.
Next we add a new attribute to the new node, using the addAttribute function.
Once the node is added, the file is written to the console just as in the previous example in which we added an element with text content.
Retrieving the value of an attribute is similar to the previous example in which we retrieved a node's text contents. In this case we'll extract the value of the URI we added in the previous section. Full code: Appendix F, Code for Retrieving Attribute Value Example.
The initial steps for this example are similar to the previous ones: parse the doc, find the element you are interested in, then enter a function to carry out the specific task required. In this case, we call getReference:
Function getReference(doc:TxmlDoc, node:TxmlNode) Local uri:String Local list:TList = node.getChildren() For node = EachIn list If node.getName() = "reference" Thenuri = node.getAttribute("uri") Print "uri: " + uri End If Next End Function
The key function is addAttribute, which returns an String containing the attribute's value. In this case,
we just print it out.
![]() |
Note |
---|---|
If you are using a DTD that declares a fixed or default value for the attribute, this function will retrieve it. |
<?xml version="1.0"?> <story> <storyinfo> <author>John Fleck</author> <datewritten>June 2, 2002</datewritten> <keyword>example keyword</keyword> </storyinfo> <body> <headline>This is the headline</headline> <para>This is the body text.</para> </body> </story>
You can open the source here.
SuperStrict Import BaH.Libxml Local docname:String = "sample.xml" parseDoc(docname) Function parseStory(doc:TxmlDoc, node:TxmlNode) Local key:String Local children:TList = node.getChildren() For node = EachIn children If node.getName() = "keyword" Then key = node.getText() Print "keyword: " + key End If Next Return End Function Function parseDoc(docname:String) Local doc:TxmlDoc Local node:TxmlNode doc = TxmlDoc.parseFile(docname) If doc = Null Then Print "Document not parsed successfully." Return End If node = doc.GetRootElement() If node = Null Then Print "empty document" doc.free() Return End If If node.getName() <> "story" Print "document of the wrong type, root node <> story" doc.free() Return End If Local children:TList = node.getChildren() For node = EachIn children If node.getName() = "storyinfo" Then parseStory(doc, node) End If Next doc.free() Return End Function
You can open the source here.
SuperStrict Import BaH.Libxml Local docname:String = "sample.xml" Local doc:TxmlDoc Local xpath:String = "//keyword" Local nodeset:TxmlNodeSet Local result:TxmlXPathObject doc = getdoc(docname) If doc Then result = getNodeSet(doc, xpath) If result nodeset = result.getNodeSet() For Local node:TxmlNode = EachIn nodeset.getNodeList() Local keyword:String = node.getText() Print "keyword: " + keyword Next result.free() End If doc.free() End If xmlCleanupParser() End Function getdoc:TxmlDoc(docname:String) Local doc:TxmlDoc = TxmlDoc.parseFile(docname) If doc = Null Then Print "Document not parsed successfully." Return Null End If Return doc End Function Function getnodeset:TxmlXPathObject(doc:TxmlDoc, xpath:String) Local context:TxmlXPathContext Local result:TxmlXPathObject context = doc.newXPathContext() If context = Null Then Print "Error in newXPathContext" Return Null End If result = context.evalExpression(xpath) context.free() If result = Null Then Print "Error in xmlXPathEvalExpression" Return Null End If If result.nodeSetIsEmpty() Then result.free() Print "No result" Return Null End If Return result End Function
You can open the source here.
SuperStrict Import BaH.Libxml Local docname:String = "sample.xml" Local keyword:String = "Blitzmax" Local doc:TxmlDoc doc = parseDoc(docname, keyword) If doc <> Null Then doc.saveFormatFile("-", False) doc.free() End If Function parseStory(node:TxmlNode, keyword:String) node.addTextChild("keyword", Null, keyword) End Function Function parseDoc:TxmlDoc(docname:String, keyword:String) Local doc:TxmlDoc Local node:TxmlNode doc = TxmlDoc.parseFile(docname) If doc = Null Then Print "Document not parsed successfully." Return Null End If node = doc.getRootElement() If node = Null Then Print "empty document" doc.free() Return Null End If If node.getName() <> "story" Then Print "document of the wrong type, root node <> story" doc.free() Return Null End If Local nodelist:TList = node.getChildren() For node = EachIn nodelist If node.getName() = "storyinfo" Then parseStory(node, keyword) End If Next Return doc End Function
You can open the source here.
SuperStrict Import BaH.Libxml Local docname:String = "sample.xml" Local uri:String = "http://blitzmax.com" Local doc:TxmlDoc doc = parseDoc(docname, uri) If doc <> Null Then doc.saveFormatFile("-", True) doc.free() End If Function parseDoc:TxmlDoc(docname:String, uri:String) Local doc:TxmlDoc Local node:TxmlNode Local newnode:TxmlNode Local newattr:TxmlAttribute doc = TxmlDoc.parseFile(docname) If doc = Null Then Print "Document not parsed successfully." Return Null End If node = doc.getRootElement() If node = Null Then Print "empty document" doc.free() Return Null End If If node.getName() <> "story" Then Print "document of the wrong type, root node <> story" doc.free() Return Null End If newnode = node.addTextChild("reference", Null, Null) newattr = newnode.addAttribute("uri", uri) Return doc End Function
You can open the source here.
SuperStrict Import BaH.Libxml Local docname:String = "sampleuri.xml" parseDoc(docname) Function getReference(doc:TxmlDoc, node:TxmlNode) Local uri:String Local list:TList = node.getChildren() For node = EachIn list If node.getName() = "reference" Then uri = node.getAttribute("uri") Print "uri: " + uri End If Next End Function Function parseDoc(docname:String) Local doc:TxmlDoc Local node:TxmlNode doc = TxmlDoc.parseFile(docname) If doc = Null Then Print "Document not parsed successfully." Return End If node = doc.getRootElement() If node = Null Then Print "empty document" doc.free() Return End If If node.getName() <> "story" Then Print "document of the wrong type, root node <> story" doc.free() Return End If getReference(doc, node) doc.free() End Function