Hello, everybody!
The script language Kinx is published with the concept of Looks like JavaScript, Feels like Ruby, Stable like AC/DC(?).
This time it's an XML library.
- Reference
- First motivation ... The post of introduction
- Kinx, I wanted a scripting language with a syntax of C family.
- Repository ... https://github.com/Kray-G/kinx
- I am waiting for pull requests.
- First motivation ... The post of introduction
XML is also often used, so it will be one of what a lot of people want to use easily with a scripting language.
XML
Parsing DOM
Build a DOM tree using Xml.parseFile()
or Xml.parseString()
. To read the file, do the following.
var doc = Xml.parseFile("xmlfile.xml");
The following is an example of directly parsing a string.
var doc = Xml.parseString(%{
<?xml version="1.0" encoding="UTF-8" ?>
<artists>
<product country="US" id="1">
<name>Power Snack</name>
<price>2400</price>
<img file="powersnack.jpg"/>
</product>
<product country="US" id="2">
<name>Babystar Icecream</name>
<price>21000</price>
<img file="babystar.jpg"/>
</product>
<product country="DE" id="3">
<name>Panic! Panic! Panic!</name>
<price>2400</price>
<img file="panic.jpg"/>
</product>
</artists>
});
The returned document object has the following methods.
Method | Content |
---|---|
documentElement() |
Gets the root document |
createElement(tagname) |
Creates an Element node |
createTextNode(text) |
Creates a Text node |
createComment(comment) |
Creates a Comment node |
createCdataSection(content) |
Creates a CDATA Section node |
createProcessingInstruction(target, data) |
Creates a Processing Instruction node |
createEntityReference(name) |
Creates an Entity Reference node |
createElementNS(nsUri, qname) |
Creates an Element node by specifying the namespace |
getElementById(id) |
Search for a node by specifying id |
getElementsByTagName(tagName) |
Returns the node of tagName as an array |
xpath(expr) |
Evaluates the XPATH of expr and returns the result as an array |
Root node
The root node is obtained using the documentElement()
method as follows.
var root = doc.documentElement();
XML node
XML nodes, including the root node, have the following properties and methods.
Properties
Properties | Content |
---|---|
type |
Node type |
name |
QName |
tagName |
Tag name |
localName |
Local name |
namespaceURI |
Namespace URI |
prefix |
Prefix |
Methods
Method | Content |
---|---|
attributes() |
Returns an attribute list as an array. |
setAttribute(qname, value) |
Set the attribute. |
setAttributeNS(nsUri, qname, value) |
Set the attribute by specifying the namespace. |
removeAttribute(qname) |
Removes an attribute. |
removeAttributeNS(nsUri, localName) |
Removes the attribute by specifying the namespace. |
parentNode() |
Returns the parent node. |
children() |
Returns the child nodes as an array. |
firstChild() |
Returns the first child node. |
lastChild() |
Returns the last child node. |
nextSibling() |
Returns the next node. |
previousSibling() |
Returns the previous node. |
appendChild(node) |
Adds a node to the child node. |
removeChild(node) |
Removes a node from child nodes. |
replaceChild(node1, node2) |
Replaces the child node. |
replaceNode(node) |
Replaces one's own node with another node. |
insertBefore(node) |
Add a node as the previous node. |
insertAfter(node) |
Add a node as the next node. |
remove() |
Removes the node. |
textContent() |
Gets the text. |
innerText() |
Gets the text. |
hasChildren() |
Returns 1 if a child node exists. |
hasAttributes() |
Returns 1 if there are attributes. |
getElementById(id) |
Search for a node by specifying id |
getElementsByTagName(tagName) |
Returns the node of tagName as an array |
xpath(expr) |
Evaluates the XPATH of expr and returns the result as an array |
XPath
XPath returns the nodes that match the XPATH expression in the form of a node set (array). The node set also has an xpath()
method, and you can use it by chaining XPATH to the narrowed down nodes.
Run the following with the sample XML document above.
var nodes = doc.xpath("//product")
.xpath("price")
.map(&(p) => p.innerText());
nodes.each(&(text) => {
System.println(text);
});
Result.
2400
21000
2400
By the way, using a block syntax and a numbered parameter supported recently, you can also write the following.
var nodes = doc.xpath("//product")
.xpath("price")
.map { => _1.innerText() };
nodes.each {
System.println(_1);
};
Sample source
I introduce the sample source included in the repo. There is Xml.Writer
which is not explained, but I think it will be helpful as it is an example that can do DOM parsing like this.
function displayXml(doc, node, indent) {
System.print(" " * indent);
if (node.type == Xml.ELEMENT_NODE) {
System.print("ELEM %s" % node.name);
} else if (node.type == Xml.TEXT_NODE) {
System.print("TEXT %s" % node.value.trim());
}
var attr = node.attributes();
for (var i = 0, len = attr.length(); i < len; ++i) {
System.print("[%s=%s]" % attr[i].name % attr[i].value);
}
System.println("");
var child = node.firstChild();
while (child) {
displayXml(doc, child, indent + 1);
child = child.nextSibling();
}
}
var doc = Xml.parseString(%{
<?xml version="1.0" encoding="UTF-8" ?>
<artists>
<product country="US" id="1">
<name>Power Snack</name>
<price>2400</price>
<img file="powersnack.jpg"/>
</product>
<product country="US" id="2">
<name>Babystar Icecream</name>
<price>21000</price>
<img file="babystar.jpg"/>
</product>
<product country="DE" id="3">
<name>Panic! Panic! Panic!</name>
<price>2400</price>
<img file="panic.jpg"/>
</product>
</artists>
});
var root = doc.documentElement();
displayXml(doc, root);
var el = root.getElementById("3");
if (el) {
el.remove();
}
System.println("");
System.println("getElementByTagName:");
var els = root.getElementsByTagName("img");
if (els.isArray) {
els.each(&(el) => displayXml(doc, el));
}
System.println("");
System.println("XPath:");
var nodes = doc.xpath("//product").xpath("price");
if (nodes.isArray) {
nodes.each(&(el) => displayXml(doc, el));
}
var xmlWriter = new Xml.Writer(System);
xmlWriter.write(doc);
xmlWriter.write(root);
Execution result.
ELEM artists
TEXT
ELEM product[country=US][id=1]
TEXT
ELEM name
TEXT Power Snack
TEXT
ELEM price
TEXT 2400
TEXT
ELEM img[file=powersnack.jpg]
TEXT
TEXT
ELEM product[country=US][id=2]
TEXT
ELEM name
TEXT Babystar Icecream
TEXT
ELEM price
TEXT 21000
TEXT
ELEM img[file=babystar.jpg]
TEXT
TEXT
ELEM product[country=DE][id=3]
TEXT
ELEM name
TEXT Panic! Panic! Panic!
TEXT
ELEM price
TEXT 2400
TEXT
ELEM img[file=panic.jpg]
TEXT
TEXT
getElementByTagName:
ELEM img[file=powersnack.jpg]
ELEM img[file=babystar.jpg]
XPath:
ELEM price
TEXT 2400
ELEM price
TEXT 21000
<artists>
<product country="US" id="1">
<name>Power Snack</name>
<price>2400</price>
<img file="powersnack.jpg" />
</product>
<product country="US" id="2">
<name>Babystar Icecream</name>
<price>21000</price>
<img file="babystar.jpg" />
</product>
</artists>
<artists>
<product country="US" id="1">
<name>Power Snack</name>
<price>2400</price>
<img file="powersnack.jpg" />
</product>
<product country="US" id="2">
<name>Babystar Icecream</name>
<price>21000</price>
<img file="babystar.jpg" />
</product>
</artists>
Conclusion
It would be nice to be able to use XPath.
And if you combine XML and Zip, you can actually read and write Xlsx files (Excel files). The Xlsx file is standardized under the name Office Open XML (with various problems), and it is created by the XML file and a Zip file, so you can read it.
However, in fact, supporting all of Office Open XML requires a lot of codes, so what I can do right away will be just a simple reading and writing. If I have time, I will challenge it.
See you next time.
Top comments (0)