An XML
element is everything from the element's start tag, to the element's end tag, both included.
In some way, the JSXMLElement
is similar to the JSXMLDocument
but prepared to be traversed thanks to the addition of different methods.
1 Traversing
Tranversion an XML
using Javascript and handling it's data it's simple. Let's see an example where we combine two functions:
-
XML
foreach, to traverseXML
children nodes - toMap, to convert an Node to a
JSON
object
Traversing XML
nodes
<script> var xml = new Ax.xml.DocumentBuilderFactory().parse(new Ax.net.URL('https://bitbucket.org/deister/axional-docs-resources/raw/master/XML/nutrition.xml')); xml.getRootElement().forEach(node => { switch (node.getTagName()) { case "food": handle_food(node); break; case "daily-values": handle_daily_values(node); break; } }); function handle_food(node) { console.log(node.toMap()); } function handle_daily_values(node) { console.log(node.toMap()); } </script>
{carb=300, sodium=2400, fiber=25, total-fat=65, protein=50, cholesterol=300, saturated-fat=20}
{carb=2, minerals={ca=0, fe=0}, fiber=0, calories=, saturated-fat=3, serving=29, sodium=210, vitamins={a=0, c=0}, total-fat=11, protein=1, name=Avocado Dip, mfr=Sunnydale, cholesterol=5}
{carb=54, minerals={ca=8, fe=20}, fiber=3, calories=, saturated-fat=1, serving=104, sodium=510, vitamins={a=0, c=0}, total-fat=4, protein=11, name=Bagels, New York Style, mfr=Thompson, cholesterol=0}
{carb=8, minerals={ca=1, fe=6}, fiber=0, calories=, saturated-fat=15, serving=115, sodium=1100, vitamins={a=0, c=2}, total-fat=32, protein=13, name=Beef Frankfurter, Quarter Pound, mfr=Armitage, cholesterol=65}
{carb=42, minerals={ca=2, fe=10}, fiber=2, calories=, saturated-fat=9, serving=198, sodium=810, vitamins={a=20, c=2}, total-fat=22, protein=10, name=Chicken Pot Pie, mfr=Lakeson, cholesterol=25}
{carb=5, minerals={ca=4, fe=2}, fiber=2, calories=, saturated-fat=0, serving=1.5, sodium=15, vitamins={a=30, c=45}, total-fat=0, protein=1, name=Cole Slaw, mfr=Fresh Quick, cholesterol=0}
{carb=1, minerals={ca=2, fe=4}, fiber=0, calories=, saturated-fat=1.5, serving=50, sodium=65, vitamins={a=6, c=0}, total-fat=4.5, protein=6, name=Eggs, mfr=Goodpath, cholesterol=215}
{carb=23, minerals={ca=6, fe=4}, fiber=2, calories=, saturated-fat=2, serving=2, sodium=20, vitamins={a=0, c=0}, total-fat=10, protein=3, name=Hazelnut Spread, mfr=Ferreira, cholesterol=0}
{carb=15, minerals={ca=0, fe=0}, fiber=1, calories=, saturated-fat=3, serving=28, sodium=180, vitamins={a=0, c=10}, total-fat=10, protein=2, name=Potato Chips, mfr=Lees, cholesterol=0}
{carb=10, minerals={ca=0, fe=0}, fiber=4, calories=, saturated-fat=0, serving=96, sodium=420, vitamins={a=0, c=0}, total-fat=5, protein=9, name=Soy Patties, Grilled, mfr=Gardenproducts, cholesterol=0}
{carb=16, minerals={ca=0, fe=0}, fiber=1, calories=, saturated-fat=14, serving=39, sodium=10, vitamins={a=0, c=0}, total-fat=19, protein=1, name=Truffles, Dark Chocolate, mfr=Lyndon's, cholesterol=25}
2 Methods
During the XMLElement
documentation, the example of XML
document used corresponds to:
Javascript
const str = ` <bolsa:inversiones xmlns:bolsa="http://www.bolsa.es" xmlns:geograf="http://www.geograf.com"> <geograf:país geograf:nombre="España"> <geograf:capital>Madrid</geograf:capital> <bolsa:capital>2000€</bolsa:capital> </geograf:país> </bolsa:inversiones>` var dbf = new Ax.xml.DocumentBuilderFactory(); var xmlobj = dbf.parse(str); var xmlroot = xmlobj.getRootElement(); console.log(xmlroot.getTagName()); console.log(xmlroot); xmlroot.forEach(node => { switch (node.getTagName()) { case "food": handle_food(node); break; case "daily-values": handle_daily_values(node); break; } }); console.log(xml);
XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <bolsa:inversiones xmlns:bolsa="http://www.bolsa.es" xmlns:geograf="http://www.geograf.com"> <geograf:país geograf:nombre="España"> <geograf:capital>Madrid</geograf:capital> <bolsa:capital>2000€</bolsa:capital> </geograf:país> </bolsa:inversiones>
The main methods that are frequently used to navigate or obtain information when working with a JSXMLElement
are the following ones:
2.1 Attributes
2.1.1 getAttributeNames
Returns a list of attribute names in a node.
const str = ` <bolsa:inversiones xmlns:bolsa="http://www.bolsa.es" xmlns:geograf="http://www.geograf.com"> <geograf:país geograf:nombre="España"> <geograf:capital>Madrid</geograf:capital> <bolsa:capital>2000€</bolsa:capital> </geograf:país> </bolsa:inversiones>` const dbf = new Ax.xml.DocumentBuilderFactory(); xml = dbf.parse(str); console.log(xml.getRootElement().getAttributeNames());
2.1.2 getAttribute
To obtain the value of a name-known attribute, the method getAttribute(String)
should be used.
Javascript
const str = ` <bolsa:inversiones xmlns:bolsa="http://www.bolsa.es" xmlns:geograf="http://www.geograf.com"> <geograf:país geograf:nombre="España"> <geograf:capital>Madrid</geograf:capital> <bolsa:capital>2000€</bolsa:capital> </geograf:país> </bolsa:inversiones>` const dbf = new Ax.xml.DocumentBuilderFactory(); xml = dbf.parse(str); return xml.getRootElement().getAttribute("xmlns:bolsa");
http://www.bolsa.es
2.1.3 getTagName
getTagName() recovers the node's name in which one is positioned at that moment, for example, being at the root element:
Javascript
<script> const str = ` <bolsa:inversiones xmlns:bolsa="http://www.bolsa.es" xmlns:geograf="http://www.geograf.com"> <geograf:país geograf:nombre="España"> <geograf:capital>Madrid</geograf:capital> <bolsa:capital>2000€</bolsa:capital> </geograf:país> </bolsa:inversiones>` const dbf = new Ax.xml.DocumentBuilderFactory(); xml = dbf.parse(str); return xml.getRootElement().getTagName(); </script>
bolsa:inversiones
2.2 DOM Traversing
Along with the previously mentioned, there are some methods that allow us to move through the DOM positioning in the different nodes, such as:
2.2.1 getFirstChildElement
Returns the first element that is in the lower level or null if not shild element exists.
Javascript
<script> const str = ` <bolsa:inversiones xmlns:bolsa="http://www.bolsa.es" xmlns:geograf="http://www.geograf.com"> <geograf:país geograf:nombre="España"> <geograf:capital>Madrid</geograf:capital> <bolsa:capital>2000€</bolsa:capital> </geograf:país> </bolsa:inversiones>` const dbf = new Ax.xml.DocumentBuilderFactory(); xml = dbf.parse(str); console.log(xml.getRootElement().getFirstChildElement()); </script>
<geograf:país xmlns:geograf="http://www.geograf.com" geograf:nombre="España"> <geograf:capital>Madrid</geograf:capital> <bolsa:capital xmlns:bolsa="http://www.bolsa.es">2000€</bolsa:capital> </geograf:país>
2.2.2 getNextSiblingElement
To move along the same depth-level, getNextSiblingElement() returns the next node with the same parent.
Javascript
<script> const str = ` <bolsa:inversiones xmlns:bolsa="http://www.bolsa.es" xmlns:geograf="http://www.geograf.com"> <geograf:país geograf:nombre="España"> <geograf:capital>Madrid</geograf:capital> <bolsa:capital>2000€</bolsa:capital> </geograf:país> </bolsa:inversiones>` const dbf = new Ax.xml.DocumentBuilderFactory(); xml = dbf.parse(str); console.log(xml.getRootElement().getFirstChildElement().getNextSiblingElement()); </script>
2.2.3 getPreviousSiblingElement
On the other hand, getPreviousSibling() obtains the previous sibling.
Javascript
<script> const str = ` <bolsa:inversiones xmlns:bolsa="http://www.bolsa.es" xmlns:geograf="http://www.geograf.com"> <geograf:país geograf:nombre="España"> <geograf:capital>Madrid</geograf:capital> <bolsa:capital>2000€</bolsa:capital> </geograf:país> </bolsa:inversiones>` const dbf = new Ax.xml.DocumentBuilderFactory(); xml = dbf.parse(str); console.log(xml.getRootElement().getFirstChildElement().getPreviousSiblingElement()); </script>
2.2.4 getParentElement
This method goes to the higher level by moving to the parent's node.
Javascript
<script> const str = ` <bolsa:inversiones xmlns:bolsa="http://www.bolsa.es" xmlns:geograf="http://www.geograf.com"> <geograf:país geograf:nombre="España"> <geograf:capital>Madrid</geograf:capital> <bolsa:capital>2000€</bolsa:capital> </geograf:país> </bolsa:inversiones>` const dbf = new Ax.xml.DocumentBuilderFactory(); xml = dbf.parse(str); console.log(xml.getRootElement().getFirstChildElement().getParentElement()); </script>
<bolsa:inversiones xmlns:bolsa="http://www.bolsa.es" xmlns:geograf="http://www.geograf.com"> <geograf:país geograf:nombre="España"> <geograf:capital>Madrid</geograf:capital> <bolsa:capital>2000€</bolsa:capital> </geograf:país> </bolsa:inversiones>
2.3 Create XML Elements
var xml = new Ax.xml.DocumentBuilderFactory().parse(` <class> <student rollno = "393"> <firstname>dinkar</firstname> <lastname>kad</lastname> <nickname>dinkar</nickname> <marks>85</marks> </student> </class>` ); var element_class = xml.getRootElement(); // Try to replace first student name to pradeep var fistnameNode = element_class.getNode("student/firstname"); console.log(fistnameNode); curr_val = fistnameNode.getElement().getTextContent(); fistnameNode.getElement().setTextContent(curr_val + " Pradeep"); console.log(fistnameNode.getElement().getTextContent()); // Create a new student node var element_student = element_class.createChild("student"); element_student.setAttribute("rollno", "1"); var text = element_student.createChild("firstname").appendText("Jhon"); var cdata = element_student.createChild("lastname").appendCDATA("A\nB"); text.replaceWholeText("Albert"); cdata.replaceWholeText("no info"); console.log(xml);
2.4 Remove XML Elements
Para poder eliminar un elemento del DOM XML
, Debemos convertir los elementos desde la implementación JSXMLElement
a la implementación estándar org.w3c.dom.Element mediante el uso del método getElement()
Esta implementación dispone del método removeChild(node) con el que podemos eliminar un nodo del DOM de XML
, y otros
muchos métodos que podemos consultar en la documentación de Java.
var dbf = new Ax.xml.DocumentBuilderFactory(); var xml = dbf.parse(` <ChisData> <Response> <Code>0</Code> </Response> <Data> <Value>XYZ</Value> </Data> </ChisData>`); nodejs = xml.getRootElement().getNode("/ChisData/Response"); nodejs.removeElement();
<ChisData>
<Data>
<Value>XYZ</Value>
</Data>
</ChisData>
var dbf = new Ax.xml.DocumentBuilderFactory(); var xml = dbf.parse(` <ChisData> <Response> <Code>0</Code> </Response> <Data> <Value>XYZ</Value> </Data> </ChisData>`); // Returns JSXMLElement nodejs = xml.getRootElement().getNode("/ChisData/Response"); console.log(nodejs); // Convert nodejs to W3 ElementNSImpl nodew3 = nodejs.getElement(); // Get parent of ResponseNode and convertit to W3 Element var rootw3 = xml.getRootElement().getElement(); rootw3.removeChild(nodew3); console.log(rootw3);
<Response>
<Code>0</Code>
</Response>
<ChisData>
<Data>
<Value>XYZ</Value>
</Data>
</ChisData>
There is another more generic way of removing a node from a XML
DOM, without actualy getting the parent manualy:
var dbf = new Ax.xml.DocumentBuilderFactory(); var xml = dbf.parse(` <ChisData> <Response> <Code>0</Code> </Response> <Data> <Value>XYZ</Value> </Data> </ChisData>`); function XMLRemoveElement(p_node) { parent = p_node.getParentElement(); parent.getElement().removeChild(p_node.getElement()); } nodejs = xml.getRootElement().getNode("/ChisData/Response"); XMLRemoveElement(nodejs); console.log(xml);
<ChisData>
<Data>
<Value>XYZ</Value>
</Data>
</ChisData>
3 Conversion
JSXMLElement
also preserves the conversion methods that JSXMLDocument
has. This means: toString()
, toBlob()
and toJSON()
among others.
These are useful because, depending on the goal, it should be necessary to obtain the output in a certain format.
3.1 toString
Returns a string representation of the XML
element in UTF-8 encoding and including XML
declaration.
Javascript
<script> const str = ` <bolsa:inversiones xmlns:bolsa="http://www.bolsa.es" xmlns:geograf="http://www.geograf.com"> <geograf:país geograf:nombre="España"> <geograf:capital>Madrid</geograf:capital> <bolsa:capital>2000€</bolsa:capital> </geograf:país> </bolsa:inversiones>` const dbf = new Ax.xml.DocumentBuilderFactory(); xml = dbf.parse(str); console.log(xml.getRootElement().toString()); </script>
<bolsa:inversiones xmlns:bolsa="http://www.bolsa.es" xmlns:geograf="http://www.geograf.com"> <geograf:país geograf:nombre="España"> <geograf:capital>Madrid</geograf:capital> <bolsa:capital>2000€</bolsa:capital> </geograf:país> </bolsa:inversiones>
At first glance, it could seem the same as the result obtained when converting to JSXMLElement
, but this time the output corresponds to a String
,
with all the implications it has (different methods, JS primitive type, etc...).
3.2 toBlob
A JSXMLElement
can be directly transferred to database as a Blob. This can be particularly useful when the database field-type corresponds to Clob/Blob.
Blob takes the filename according to root element, tag name and extension ".xml". Content type is set as "text/xml".
3.3 toJSON
At some point, moving through XML
untill finding a concrete node can become a bit tedious, for example, when trying to get the value of a name-known deep node.
In these cases, the JSON
notation can be helpful. A JSXMLElement
can be converted to a JSON
object easily by calling toJSON().
The returned object is a Java org.json.JSONObject. It can be converted to JavaScript JSON
by using
toMap()
on it.
Using directly this java object and calling get method to search elements, throws an exception if element is not found: json.get("NON-EXISTENT"). You can use json.has("NON-EXISTENT") to verify if element exists before trying to get it.
In the previous example, the capital can be obtained by converting the JSXMLElement
into a JSON
JS object and moving through the properties:
Javascript
var dbf = new Ax.xml.DocumentBuilderFactory(); var xml = dbf.parse( ` <bolsa:inversiones xmlns:bolsa="http://www.bolsa.es" xmlns:geograf="http://www.geograf.com"> <geograf:país geograf:nombre="España"> <geograf:capital>Madrid</geograf:capital> <bolsa:capital>2000€</bolsa:capital> </geograf:país> </bolsa:inversiones> ` ); var jsonMapXML = xml.toJSON().toMap(); console.log("JSON Map: ") console.log(jsonMapXML); var jsonXML = xml.toJSON(); console.log("JSON: ") console.log(jsonXML);
JSON Map:
{bolsa:inversiones={xmlns:geograf=http://www.geograf.com, xmlns:bolsa=http://www.bolsa.es, geograf:país={geograf:nombre=España, bolsa:capital=2000€, geograf:capital=Madrid}}}
JSON:
{"bolsa:inversiones":{"xmlns:geograf":"http://www.geograf.com","xmlns:bolsa":"http://www.bolsa.es","geograf:país":{"geograf:nombre":"España","bolsa:capital":"2000\u20ac","geograf:capital":"Madrid"}}}
3.4 toMap
A JSXMLElement
can also be converted to a java Map. The used as JSON
object. This method is similar than previous (JSON
)
method but it will exclude attributes.
Javascript
var dbf = new Ax.xml.DocumentBuilderFactory(); var xml = dbf.parse( ` <bolsa:inversiones xmlns:bolsa="http://www.bolsa.es" xmlns:geograf="http://www.geograf.com"> <geograf:país geograf:nombre="España"> <geograf:capital>Madrid</geograf:capital> <bolsa:capital>2000€</bolsa:capital> </geograf:país> </bolsa:inversiones> ` ); var jsonMapXML = xml.toMap(); console.log(jsonMapXML);
{geograf:país={bolsa:capital=2000€, geograf:capital=Madrid}}