Version 3.69 of MUSHclient adds a new function (xmlread) to the "utils" table, which uses MUSHclient's internal XML parser to parse an XML string you supply. This effectively would let you parse triggers, aliases etc. that you have copied to the clipboard as text (or created with ExportXML script routine), and see exactly what each value is set to. Or, by reading a MUSHclient world file into memory as a string, you could parse that.
The XML parser is not necessarily 100% industry-standard XML parsing, however it is the method MUSHclient uses for its own XML documents, and should be reasonably compatible with standard XML unless you use some of the more fancy XML extensions. It should certainly parse the XML output by MUSHclient itself (eg. triggers, aliases, world files, plugins) as that is the same routine it uses to read them in.
You pass to the parser a single string, which is the XML to be parsed. If the parsing is successful three results are returned:
If the parsing fails, three results are returned:
You can pass the first 2 results to "assert" to quickly check if the parsing was successful.
Each node consists of a table with the following entries:
Example of use:
Output:
You can see from the above that the "root" node is really just an unnamed node which is the placeholder for the top level nodes (ie. the first "real" node is a child of the root node). In this case the node "foo" is the first child of the root node. The node "goat" is the 2nd child of the root node.
Custom entities are declared in the <!DOCTYPE> directive, like this:
If your XML document contains such entries, they will appear in the "custom entities" table returned as the 3rd result from utils.xmlread.
Note that custom entities are automatically replaced in the body of the document, it is not possible to reconstruct from the nodes where they occurred.
Another example, parsing a standard alias:
Using tprint to print the result gives this:
Here you can see the first child node (key 1, name "aliases") is the "all aliases" node. Under that (a child of that) is the node (key 1, name "alias") for the first alias. That also has a child, the <send> node, which is what the alias sends.
Thus the hierarchy is:
root (unnamed) -> aliases -> alias -> send
The XML parser is not necessarily 100% industry-standard XML parsing, however it is the method MUSHclient uses for its own XML documents, and should be reasonably compatible with standard XML unless you use some of the more fancy XML extensions. It should certainly parse the XML output by MUSHclient itself (eg. triggers, aliases, world files, plugins) as that is the same routine it uses to read them in.
You pass to the parser a single string, which is the XML to be parsed. If the parsing is successful three results are returned:
- The root node (all other nodes are children of this node)
- The root document name (eg. "muclient")
- A table of custom entities in the document, or nil if no custom entities
If the parsing fails, three results are returned:
- nil - to indicate failure
- The error reason
- The line the error occurred at
You can pass the first 2 results to "assert" to quickly check if the parsing was successful.
Each node consists of a table with the following entries:
- name - name of the node (eg. <trigger>foo</trigger> - the name is "trigger")
- content - contents of the node (eg. <trigger>foo</trigger> - the content is "foo")
- empty - boolean to indicate if the node is empty. (eg. <br/> is an empty node)
- line - which line in the XML string the node occurred on (eg. line 5)
- attributes - a table of attributes for this node, keyed by the attribute name
(eg. "world_file_version"="15"). Attribute names have to be unique so we can used a keyed lookup to find them.
The attributes table is not present if there are no attributes defined.
- nodes - a table of child nodes, keyed by ascending number (the order they appeared in). Each child node has the same contents as described above.
Children are not necessarily unique (eg. there may be more than one <trigger> node in a document) so they are keyed by number, and not by node name.
The nodes table is not present if there are no children of this node.
Example of use:
a, b, c = utils.xmlread [[
<foo width="1" height="2">
contents of foo
<bar west="true" fish="bicycle">
child of foo
</bar>
</foo>
<goat blood="100">eep</goat>
]]
if not a then
print ("error on line = ", c)
end -- if
assert (a, b)
tprint (a)
Output:
"line"=0
"name"=""
"content"=""
"nodes":
1:
"line"=2
"name"="foo"
"nodes":
1:
"line"=4
"name"="bar"
"content"="
child of foo
"
"attributes":
"fish"="bicycle"
"west"="true"
"content"="
contents of foo
"
"attributes":
"height"="2"
"width"="1"
2:
"line"=8
"name"="goat"
"content"="eep"
"attributes":
"blood"="100"
You can see from the above that the "root" node is really just an unnamed node which is the placeholder for the top level nodes (ie. the first "real" node is a child of the root node). In this case the node "foo" is the first child of the root node. The node "goat" is the 2nd child of the root node.
Custom entities are declared in the <!DOCTYPE> directive, like this:
<!DOCTYPE muclient [
<!ENTITY afk_command "afk" >
<!ENTITY timer_mins "5" >
<!ENTITY timer_secs "0" >
<!ENTITY afk_message "You are now afk." >
<!ENTITY not_afk_message "You are no longer afk." >
]>
If your XML document contains such entries, they will appear in the "custom entities" table returned as the 3rd result from utils.xmlread.
Note that custom entities are automatically replaced in the body of the document, it is not possible to reconstruct from the nodes where they occurred.
Another example, parsing a standard alias:
<aliases>
<alias
name="test"
match="eat"
sequence="100"
>
<send>eat food</send>
</alias>
</aliases>
Using tprint to print the result gives this:
"line"=0
"name"=""
"nodes":
1:
"line"=2
"name"="aliases"
"nodes":
1:
"line"=3
"name"="alias"
"nodes":
1:
"line"=8
"content"="eat food"
"name"="send"
"content"="
"
"attributes":
"sequence"="100"
"name"="test"
"match"="eat"
"content"="
"
"content"=""
Here you can see the first child node (key 1, name "aliases") is the "all aliases" node. Under that (a child of that) is the node (key 1, name "alias") for the first alias. That also has a child, the <send> node, which is what the alias sends.
Thus the hierarchy is:
root (unnamed) -> aliases -> alias -> send