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 traverse XML children nodes
  • toMap, to convert an Node to a JSON object

Example

Traversing XML nodes

Copy
<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:

Example

Javascript

Copy
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

Copy
<?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.

Copy
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.

Example

Javascript

Copy
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");
Copy
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:

Example

Javascript

Copy
<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>
Copy
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.

Example

Javascript

Copy
<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>
Copy
<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.

Example

Javascript

Copy
<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.

Example

Javascript

Copy
<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.

Example

Javascript

Copy
<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>
Copy
<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

Copy
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.

Copy
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>
Copy
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:

Copy
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.

Example

Javascript

Copy
<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>
Copy
<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:

Example

Javascript

Copy
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.

Example

Javascript

Copy
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}}