About the Plugin

 

This plugin wraps the XML parsing library by Frank Vanden Berghen.  The source code for it can be downloaded from this location:

 

http://iridia.ulb.ac.be/~fvandenb/tools/xmlParser.html.

 

All commands have help implemented.  This help can be accessed by tying the command with the '-h' flag or by using the Maya help system (type 'help commandname').

 

Any bugs, questions, comments should be reported to: w.david.lewis@gmail.com.

 

Some Basic XML

If you're already familiar with XML, you can skip to the next section.

 

<?xml version="1.0" encoding="utf-8"?>

<element attr1 = "value">

  Data item 1

  Data item 2

  <childelement>

  </childelement>

</element>

 

In this example XML, you can see all the all the basic pieces in an XML file.

 

The first line '<?xml version="1.0" encoding="utf-8"?>' is the declaration element.  It describes the file as XML and tells the XML version and the encoding.  This version of the XML plugin will always use utf-8 as the encoding.

 

<element> is an XML element.  It has one attribute called 'attr1'.  The value of this attribute is 'value'.  The element also contains two data items and one child element (called 'childelement').  There can be multiple child elements.  Data elements and child elements can be intermixed.  Child elements can have attributes of their own and have zero or more child elements and data items.  Child elements are just elements.

 

For a detailed description of XML, please see:

 

http://www.w3.org/TR/2000/REC-xml-20001006

 

Rightly or wrongly, in the following documentation I will use the terms XML element and XML node synonymously.

 

Handling XML with this plugin in MEL

 

Since we can't add new types in MEL, we must have a way to deal with XML elements.  This plugin uses a mechanism similar to what the 'fopen' MEL command does for files.  'fopen' returns an integer that represents the file you are reading from or writing to.  You perform operations on the file and then close it when you're done.

 

Using this plugin, XML element nodes are represented by a handle; this handle is an integer.  You manipulate a node by getting access to the handle for that node and performing operations on it.  You can't manipulate a node without first getting the handle to it.

 

You start with the top-level node and navigate down by querying the node for its children.  You can also query a node for its attributes and its data items.

 

XML that has been loaded is referred to as an XML document.  You can have multiple XML documents open at once.

 

XML That Can Be Parsed by this Plugin

This library is pretty forgiving in the XML that it will read.  It will read XML with or without an XML declaration node.  It will read XML that is wrapped in a containing XML node or just a group of nodes.

XML with a declaration node

This is an example of XML that contains a declaration node.

 

<?xml version="1.0" encoding="utf-8"?>

<element_a>

    <element_b1/>

    <element_b2>

        <element_c1/>

        <element_c2/>

    </element_b2>

    <element_b3/>

</element_a>

 

When this XML is parsed by xmlFromFile or xmlFromString, a handle to the declaration node is returned.  The top-level containing node ("element_a1" in this case) is the first and only child element of the declaration element.

 

XML with a single containing node

Here is an example XML that has a single XML element the top-level.

 

<element_a>

    <element_b1/>

    <element_b2>

        <element_c1/>

        <element_c2/>

    </element_b2>

    <element_b3/>

</element_a>

 

When this XML is parsed by xmlFromFile or xmlFromString, a handle is returned to the containing XML element ('element_a').  This element will have three children, one corresponding to element_b1, element_b2 and element_b3.

 

XML with no containing node

Here is an example XML that has no single top-level element that contains everything else.

 

<element_a1>

    <element_b1/>

    <element_b2/>

</element_a1>

<element_a2>

    <element_b1/>

    <element_b2/>

</element_a2>

<element_a3>

    <element_b1/>

    <element_b2/>

</element_a3>

 

When this XML is parsed by xmlFromFile or xmlFromString, a handle is returned to a fictitious top XML element called '$/'.  In the above example, the handle is returned to '$/', and it has three child elements: 'element_a1', 'element_a2' and 'element_a3'.

 

The '$/' is not written out by the xmlToFile or the xmlToString command.  If you load the XML example above and then write it back out, you should get the same XML you started with.

 

Just like you can have multiple files open at once, you can have multiple XML documents open a once.

 

Command Reference

This plugin provides 8 commands.

 

There are four commands for loading and saving XML.  Two are for reading to/from a string and two for reading to/from a file.  All commands that load XML return an integer handle to the top-level element in the XML.

 

There is a fifth command for releasing the loaded XML when you’re done reading it.

 

There are three commands for manipulating the XML document once it’s been loaded.

xmlFromFile

usage: int $handle = `xmlFromFile filename`;

 

Flags:

      xmlFromFile has no flags

 

This command returns a handle to the top-level node in the specified XML file.  The top-level node can be a declaration node, an XML node or the fictitious '$/' node.

 

xmlFromString

usage: int $handle = `xmlFromString "xmlstring"`;

 

Flags:

      xmlFromString has no flags

 

This command returns a handle to the top-level node in the specified XML file.  The top-level node can be a declaration node, an XML node or the fictitious '$/' node.

 

xmlToFile

usage: xmlToFile [flags] handle filename

 

Flags:

-f, -format

formats the XML to be more human readable

-dec, -declaration

writes a declaration node to the XML

 

handle is the handle to the XML node to save to a file.  This handle can be for a top-level element or an element in the middle of the tree.

 

filename is the filename to write the XML to.

 

xmlToString

usage: string $s = `xmlToString [flags] handle`;

 

Flags:

-f, -format

formats the XML to be more human readable.

 

handle is the handle to the XML element to convert to a string.  This handle can be for a top-level element or an element in the middle of a tree.

 

xmlReleaseDocument

Usage: xmlReleaseDocument handle;

 

Flags: none

 

Releases all the memory used by an XML document and all of its children.  This will invalidate all the handles from any children that you have acquired.

 

handle is the handle to the top-level XML node.  This command will only work with top-level nodes (the declaration node, the containing XML element or the fictitious ‘$/’ element).

 

xmlElement

Used for querying an XML element about its child elements and create new XML elements.  Can also delete child nodes, delete attributes and delete data items.

 

Usage: xmlElement [flags] handle;

Return value depends on the combination of flags being passed

      Supports query mode, edit mode, and create mode.

 

Flags:

Flag

Description

Mode

-e, -edit

places the command in edit mode

 

-q, -query

places the command in query mode

 

-r, -remove

removes the specified sub-part of the element (attribute, data, or child node) [e]

 

-a, -attribute

operation is performed on an attribute of the xml element

[e] [q]

-c, -child

operation is performed on a child element of the xml element

[c] [e] [q]

-dt, -data

operation is performed on a data item of the xml element

[e] [q]

-dec, -declaration

whether the element is a declaration

[q]

-i, -index

specifies the sub-part by index

[c] [e] [q]

-n, -name

specifies the sub-part by name

[c] [e] [q]

 

For the purposes of this command, a sub-part of an element is an attribute, a child, or a data item.  Sub-parts may be specified by name or by index.  In general, either the name or the index may be specified but not both.  If there are multiple sub-parts of the same type with the same name (which is perfectly legal XML), the sub-parts must be accessed by index rather than by name.  If accessed by name, in general, only the first of those sub-parts will be acted upon which is generally not what you want. Indices are zero-based (e.g. the first element is index 0).

 

In general, querying for a child, attribute or data item without specifying the sub-part by name or index will return the count of the sub-parts.

 

XmlElement Examples

Querying Whether an Element is a Declaration node

int $h = `xmlFromString "<?xml version="1.0" encoding="utf-8"?><element_a />"`;

int $isDeclaration = `xmlElement -q -dec $h`;

 

In this example, $isDeclaration will be true (equal to one) since the top-level node is a declaration node.

 

Querying Attribute Count

int $h = `xmlFromString "<element_a attr1="one" attr2='two'/>"`;

int $attributeCount = `xmlElement -q -attribute $h`;

 

In this example $attributeCount will contain the number of attributes on the XML element (in this case, 2).

Querying Data Count

int $h = `xmlFromString "<element_a>Data 1\nData2\n</element_a>"`;

int $dataCount = `xmlElement -q -data $h`;

 

In this example, $dataCount will contain the number of data items in the XML (which will be two in this case).

Querying Child Count

int $h = `xmlFromString "<element_a><child1 /><child2 /></element_a>"`;

int $childCount = `xmlElement -q -child $h`;

 

This example queries a node for the number of child elements it contains.  $childCount will contain the number of child elements underneath the top-level element (in this case, two).

Querying for a Child XML element

These are examples of querying an XML element for a child element.

 

int $h = `xmlFromString "<element_a><child1 /><child2 /></element_a>"`;

int $childHandle = `xmlElement -q -child -index 1 $h`;

 

This example querys for a child XML element by index.  In this case, $childHandle will contain the handle to the second child (the <child2 /> element) since indices are zero-based.

 

int $h = `xmlFromString "<element_a><child1 /><child2 /></element_a>"`;

int $childHandle = `xmlElement -q -child -name "child1" $h`;

 

This example queries for a child XML element by name.  In this case, $childElement will contain the handle to the first child element of <element_a> (the <child1 /> element).

 

Querying for an Element's Parent

 

int $h = `xmlFromString "<element_a><child1 /><child2 /></element_a>"`;

int $childHandle = `xmlElement -q -child -name "child1" $h`;

int $rootParent = `xmlElement -q -parent $h`;

int $childParent = `xmlElement -q -parent $childHandle`;

 

This example queries for the parent of the root node and the parent of the child.  In this case, $rootParent will be equal to -1 (the parent of a top-level node will be -1) and $childParent will be equal to $h.

 

Creating a Child Element

int $h = `xmlFromString "<element_a><child1 /><child2 /></element_a>"`;

int $childHandle = `xmlElement -child -name "child3" $h`;

 

If the index flag isn't present when creating a new element, the new element will go at the end of the existing elements.  If an index is provided, the new element will be inserted after that point.  A value of ‘-1’ will insert at the beginning of the list of children.

 

Creating a New Top-level Element

int $h = `xmlElement -child -name "top" -1`;

 

This example will create a new top-level XML element.  Specifying a -1 as the parent indicates the element should be a top-level element.  The new document should be destroyed with xmlReleaseDocument when you're done with it.

 

Edit the name of an Element

int $h = `xmlFromString "<element_a><child1 /><child2 /></element_a>"`;

xmlElement -e -name "top" $h;

 

This command changes the name of the top XML element from "element_a" to "top".

 

Deleting a Child

int $h = `xmlFromString "<element_a><child1 /><child2 /></element_a>"`;

xmlElement -e -remove -child -index 0 $h;

 

This example deletes the child at index position zero ("child1").  The child can be specified by name or by index.

 

Deleting an Attribute

int $h = `xmlFromString "<element_a attr1="one" attr2='two'/>"`;

xmlElement -e -remove -attribute -index 0 $h;

 

This example deletes the attribute at index position zero ("attr1").  The attribute can be specified by name or by index.

 

Deleting a Data Item

int $h = `xmlFromString "<element_a>Data 1\nData2\n</element_a>"`;

xmlElement -e -remove -data -index 0 $h;

 

This example deletes the data item at index position zero ("Data 1").  The data can be specified by name or by index.

 

xmlAttribute

The 'xmlAttribute' command is used to query the name, value and index position of an attribute.  It can also be used to edit the name and value of an attribute and add new attributes to an XML element.

 

Usage: xmlAttribute [flags] handle;

Return value depends on the combination of flags being passed

Supports query mode, edit mode, and create mode.

 

Flags:

Flag

Description

Mode

-e, -edit

places the command in edit mode

 

-q, -query

places the command in query mode

 

-i, -index

specifies the attribute by index

[c] [e] [q]

-n, -name

specifies the attribute by name

[c] [e] [q]

-v, -value

specifies the value of the attribute

[c] [e]

 

xmlAttribute Examples

Querying the Name of an Attribute

int $h = `xmlFromString "<element_a attr1="one" attr2='two'/>"`;

string $attributeName = `xmlAttribute -q -index 0 -name $h`;

 

This example returns the name of the attribute at index position zero.  When querying an attribute name, it must be specified by name.

 

Querying the Value of an Attribute

int $h = `xmlFromString "<element_a attr1="one" attr2='two'/>"`;

string $attributeName = `xmlAttribute -q -index 0 -value $h`;

 

This example returns the value of the attribute at index position zero.  The attribute can be specified by index or by name.

 

Querying the Index of an Attribute

int $h = `xmlFromString "<element_a attr1="one" attr2='two'/>"`;

int $attributeIndex = `xmlAttribute -q -name "attr1" -index $h`;

 

This example returns the index of the attribute named "attr1".  When querying the index of an attribute it must be specified by name.

 

Editing the Value of an Attribute

int $h = `xmlFromString "<element_a attr1="one" attr2='two'/>"`;

xmlAttribute -e -name "attr1" -value "new value $h`;

 

This example changes the value of the attribute named "attr1" from "one" to "new value".  When editing the value of an attribute, it may be specified by index or by name.

 

Editing the Name of an Attribute

int $h = `xmlFromString "<element_a attr1="one" attr2='two'/>"`;

xmlAttribute -e -index -name "new name" $h`;

 

This example changes the name of the attribute named "attr1" from "attr1" to "new name".  When editing the name of an attribute, it must be specified by index.

 

Creating a New Attribute on an Element

int $h = `xmlFromString "<element_a attr1="one" attr2='two'/>"`;

xmlAttribute -name "attr3" -value "three" $h`;

 

This example adds a new attribute name "attr3" with a value of "three" to the XML node.

 

xmlData

The 'xmlData' command is used to query the value of an attribute.  It can also be used to edit the value of a data item and add new data items to an XML element.

 

Usage: xmlData [flags] handle;

Return value depends on the combination of flags being passed

      Supports query mode, edit mode, and create mode.

 

Flags:

-e, -edit

places the command in edit mode

 

-q, -query

places the command in query mode

 

-i, -index

specifies the data by index

[c] [e] [q]

-v, -value

specifies the value of the attribute

[c] [e] [q]

 

xmlData Examples

Querying the Value of a Data Item

int $h = `xmlFromString "<element_a>Data item</element_a>"`;

string $dataValue = `xmlAttribute -q -index 0 $h`;

 

This example queries the value of the first data item and returns it.  Data items must be specified by index.

 

Editing the Value of a Data Item

int $h = `xmlFromString "<element_a>Data item</element_a>"`;

string $dataValue = `xmlAttribute -e -index 0 -value "New Data" $h`;

 

This example edits the value of the first data item and changes it from "Data item" to "New Data".  Data items must be specified by index.

 

Creating a New Data Item on an Element

int $h = `xmlFromString "<element_a>Data item</element_a>"`;

string $dataValue = `xmlAttribute -index 0 -value "New Data" $h`;

 

This example creates a new data item.  The location of the new item may be specified by index.  If the index flag is not set, then the new data item is added to the end of the data items.