Back to Blog Home
← all posts

Handle XML Response from SOAP service in NativeScript

May 4, 2017 — by Nikolay Tsonev

In those cases when a service returns an XML response, you could use both xmldom and xpath node plugins to handle the request result. xmldom allows you to parse the received response. xpath gives you a simple way to read the text content and the value of the specific attribute while using its name from the XML. This solution can be used in both pure NativeScript projects and NativeScript Angular 2 projects.

First of all to use this solution, run the following commands to install xmldom and xpath

  1. npm install xmldom --save
  2. npm install xpath --save

Those two commands save the plugins as dependencies in the project package.json file.

Using in a NativeScript JavaScript Project

<Page xmlns="http://schemas.nativescript.org/tns.xsd"navigatingTo="navigatingTo" class="page">
    <Page.actionBar>
        <ActionBar title="My App" icon="" class="action-bar">
        </ActionBar>
    </Page.actionBar>
    <StackLayout class="p-20">
        <Label text="Tap the button" class="h1 text-center"/>
        <Button text="TAP" tap="onTap" class="btn btn-primary btn-active"/>
        <Label text="{{ message }}" class="h2 text-center"textWrap="true"/>
    </StackLayout>
</Page>

1) Make an HTTP request:

var http = require("http");
var createViewModel = require("./main-view-model").createViewModel;

http.request({
    url: "https://httpbin.org/post",
    method: "POST",
    headers: { "Content-Type": "application/json" },
    content:
                "<?xml version='1.0' encoding='UTF-8'?>"+
                    "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' >"+
                       "<soapenv:Body>"+
                          "<login xmlns='http://test.com'>"+
                             "<timestamp >2017-04-22T14:40:57.655Z</timestamp>"+
                             "<version >4.2</version>"+
                             "<short-message author='J. K. Rowling' >Invalid webservice credentials.</short-message>"+
                             "<long-message>Sample xml responce</long-message>"+
                          "</login>"+
                       "</soapenv:Body>"+
                    "</soapenv:Envelope>"
})
.then(function (response) {
    }, function (e) {
    console.log("Error: " +e);
});

2) Parse the received string with xmldom:

var http = require("http");
var createViewModel = require("./main-view-model").createViewModel;
var dom = require("xmldom").DOMParser;
 
var result = response.content.toJSON();
try{
   var doc = new dom().parseFromString(result["data"]);
}
catch(e){
   console.log("parsing error "+e);
}

console.log("Parsed! " + doc);

3) Setup the needed namespaces:

var http = require("http");
var createViewModel = require("./main-view-model").createViewModel;
var dom = require("xmldom").DOMParser;
var xpath = require("xpath")

var result = response.content.toJSON();
try{
   var doc = new dom().parseFromString(result["data"]);
}
catch(e){
   console.log("parsing error "+e);
}
console.log("Parsed! " + doc);
var select = xpath.useNamespaces({
  "envlp": "http://schemas.xmlsoap.org/soap/envelope/",
   "lg":"http://test.com"
);

4) Search for the needed value or attribute:

var http = require("http");
var createViewModel = require("./main-view-model").createViewModel;
var dom = require("xmldom").DOMParser;
var xpath = require("xpath")

var result = response.content.toJSON();
try{
   var doc = new dom().parseFromString(result["data"]);
}
catch(e){
   console.log("parsing error "+e);
}
console.log("Parsed! " + doc);
var select = xpath.useNamespaces({
            "envlp": "http://schemas.xmlsoap.org/soap/envelope/",
  "lg":"http://test.com"
});

//---------get value---------

try {
  console.log("Result: '" + select("//envlp:Envelope/envlp:Body/lg:login/lg:timestamp/text()", doc) + "'");
} catch(e) {

console.log("Error getting the value" + e);

}

//---------get Attribute---------

try {
   console.log("Result: '" + select("//envlp:Envelope/envlp:Body/lg:login/lg:short-message/@author", doc) + "'");
} catch(e) {
   console.log("Error getting the value" + e);
}

5) Final result:

var http = require("http");
var createViewModel = require("./main-view-model").createViewModel;
var dom = require("xmldom").DOMParser;
var xpath = require("xpath")

function onNavigatingTo(args) {
   var page = args.object;
   page.bindingContext = createViewModel();
}

exports.onNavigatingTo = onNavigatingTo;

function onTap(args){
   http.request({
     url: "https://httpbin.org/post",
     method: "POST",
     headers: { "Content-Type": "application/json" },
     content:

    "<?xml version='1.0' encoding='UTF-8'?>"+
    "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' >"+
       "<soapenv:Body>"+
          "<login xmlns='http://test.com'>"+
             "<timestamp >2017-04-22T14:40:57.655Z</timestamp>"+
             "<version >4.2</version>"+
             "<short-message author='J. K. Rowling' >Invalid webservice credentials.</short-message>"+
             "<long-message>Sample xml responce</long-message>"+
          "</login>"+
       "</soapenv:Body>"+
    "</soapenv:Envelope>"
    })
    
    .then(function (response) {
       var result = response.content.toJSON();
    try{
       var doc = new dom().parseFromString(result["data"]);
    }
    
    catch(e){
       console.log("parsing error "+e);
    }
    
    console.log("Parsed! " + doc);
       var select = xpath.useNamespaces({
      "envlp": "http://schemas.xmlsoap.org/soap/envelope/",
      "lg":"http://test.com"
    });
    
    //---------get value---------
    
    try {
       console.log("Result: '" + select("//envlp:Envelope/envlp:Body/lg:login/lg:timestamp/text()", doc) + "'");
    } catch(e) {
      console.log("Error getting the value" + e);
    }
    
    //---------get Attribute---------
    try {
       console.log("Result: '" + select("//envlp:Envelope/envlp:Body/lg:login/lg:short-message/@author", doc) + "'");
    } catch(e) {
       console.log("Error getting the value" + e);
    }
    
    }, function (e) {
       console.log("Error: " +e);
    });

}

exports.onTap = onTap;

Using in a NativeScript TypeScript Project

<Page xmlns="http://schemas.nativescript.org/tns.xsd"navigatingTo="navigatingTo" class="page">
    <Page.actionBar>
        <ActionBar title="My App" icon="" class="action-bar">
        </ActionBar>
    </Page.actionBar>
    <StackLayout class="p-20">
        <Label text="Tap the button" class="h1 text-center"/>
        <Button text="TAP" tap="onTap" class="btn btn-primary btn-active"/>
        <Label text="{{ message }}" class="h2 text-center"textWrap="true"/>
    </StackLayout>
</Page>

1) Make HTTP request:

import { EventData } from 'data/observable';
import { Page } from 'ui/page';
import {request} from "http"
import { HelloWorldModel } from './main-view-model';

request({
   url: "https://httpbin.org/post",
   method: "POST",
   headers: { "Content-Type": "application/json" },
   content:
"<?xml version='1.0' encoding='UTF-8'?>"+
"<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' >"+
   "<soapenv:Body>"+
      "<login xmlns='http://test.com'>"+
         "<timestamp >2017-04-22T14:40:57.655Z</timestamp>"+
         "<version >4.2</version>"+
         "<short-message author='J. K. Rowling' >Invalid webservice credentials.</short-message>"+
         "<long-message>Sample xml responce</long-message>"+
      "</login>"+
   "</soapenv:Body>"+
"</soapenv:Envelope>"
})

.then(function (response) {
 }, function (e) {
  console.log("Error: " +e);
});

2) Parse the received string with xmldom:

import { EventData } from 'data/observable';
import { Page } from 'ui/page';
import {request} from "http"
import { HelloWorldModel } from './main-view-model';
import { DOMParser as dom } from "xmldom";

var result = response.content.toJSON();
try{
   var doc = new dom().parseFromString(result["data"]);
}

catch(e){
   console.log("parsing error "+e);
}
console.log("Parsed! " + doc);

3) Setup the needed namespaces:

import { EventData } from 'data/observable';
import { Page } from 'ui/page';
import {request} from "http"
import { HelloWorldModel } from './main-view-model';
import { DOMParser as dom } from "xmldom";
import * as Xpath from "xpath";

var result = response.content.toJSON();
try{
   var doc = new dom().parseFromString(result["data"]);
}

catch(e){
   console.log("parsing error "+e);
}

console.log("Parsed! " + doc);
var select = Xpath.useNamespaces({
   "envlp": "http://schemas.xmlsoap.org/soap/envelope/",

  "lg":"http://test.com"
});

4) Search for the needed value or attribute:

import { EventData } from 'data/observable';
import { Page } from 'ui/page';
import {request} from "http"
import { HelloWorldModel } from './main-view-model';
import { DOMParser as dom } from "xmldom";
import * as Xpath from "xpath";

var result = response.content.toJSON();
try{
   var doc = new dom().parseFromString(result["data"]);
}

catch(e){
   console.log("parsing error "+e);
}
console.log("Parsed! " + doc);
"envlp": "http://schemas.xmlsoap.org/soap/envelope/",
  "lg":"http://test.com"
});

//---------get Value---------
try {
  console.log("Result: '" + select("//envlp:Envelope/envlp:Body/lg:login/lg:timestamp/text()", doc) + "'");
} catch(e) {
   console.log("Error getting the value" + e);
}
//---------get Attribute---------
try {
   console.log("Result: '" + select("//envlp:Envelope/envlp:Body/lg:login/lg:short-message/@author", doc) + "'");
} catch(e) {
   console.log("Error getting the value" + e);
}

5) Final result:

import { EventData } from 'data/observable';
import { Page } from 'ui/page';
import {request} from "http"
import { HelloWorldModel } from './main-view-model';
import { DOMParser as dom } from "xmldom";
import * as Xpath from "xpath";
export function navigatingTo(args: EventData) {
   let page = <Page>args.object;
   page.bindingContext = new HelloWorldModel();
}

export function onTap(args){
    request({
       url: "https://httpbin.org/post",
       method: "POST",
       headers: { "Content-Type": "application/json" },
       content:
    "<?xml version='1.0' encoding='UTF-8'?>"+
    "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' >"+
       "<soapenv:Body>"+
          "<login xmlns='http://test.com'>"+
             "<timestamp >2017-04-22T14:40:57.655Z</timestamp>"+
             "<version >4.2</version>"+
             "<short-message author='J. K. Rowling' >Invalid webservice credentials.</short-message>"+
             "<long-message>Sample xml responce</long-message>"+
          "</login>"+
       "</soapenv:Body>"+
    "</soapenv:Envelope>"
    })
    
    .then(function (response) {
       var result = response.content.toJSON();
    try{
       var doc = new dom().parseFromString(result["data"]);
    }
    
    catch(e){
       console.log("parsing error "+e);
    }
    
    console.log("Parsed! " + doc);
    
    
    var select = Xpath.useNamespaces({
                "envlp": "http://schemas.xmlsoap.org/soap/envelope/",
       "lg":"http://test.com"
    });
    
    //---------get value---------
    try {
       console.log("Result: '" + select("//envlp:Envelope/envlp:Body/lg:login/lg:timestamp/text()", doc) + "'");
    } catch(e) {
       console.log("Error getting the value" + e);
    }
    
    //---------get Attribute---------
    try {
       console.log("Result: '" + select("//envlp:Envelope/envlp:Body/lg:login/lg:short-message/@author", doc) + "'");
    } catch(e) {
       console.log("Error getting the value" + e);
    }
    }, function (e) {
    console.log("Error: " +e);
    });
}

Using in a NativeScript Angular Project

<ActionBar title="My App" class="action-bar">
</ActionBar>
<StackLayout class="page">
    <Label text="Sample XMl Parsing" textWrap="true"></Label>
    <Button text="Make requiest" (tap)="onTap($event)"></Button>
</StackLayout>

1) Make HTTP request:

import { Component, OnInit } from "@angular/core";
import {request} from "http";
import { Item } from "./item";
import { ItemService } from "./item.service";

request({
   url: "https://httpbin.org/post",
   method: "POST",
   headers: { "Content-Type": "application/json" },
   content:

    "<?xml version='1.0' encoding='UTF-8'?>"+
    "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' >"+
       "<soapenv:Body>"+
          "<login xmlns='http://test.com'>"+
             "<timestamp >2017-04-22T14:40:57.655Z</timestamp>"+
             "<version >4.2</version>"+
             "<short-message author='J. K. Rowling' >Invalid webservice credentials.</short-message>"+
             "<long-message>Sample xml responce</long-message>"+
          "</login>"+
       "</soapenv:Body>"+
    "</soapenv:Envelope>"
    })

.then(function (response) {
}, function (e) {
   console.log("Error: " +e);
});

2) Parse the received string with xmldom:

import { Component, OnInit } from "@angular/core";
import { DOMParser as dom } from "xmldom";
import {request} from "http";
import { Item } from "./item";
import { ItemService } from "./item.service";

var result = response.content.toJSON();
try{
   var doc = new dom().parseFromString(result["data"]);
}

catch(e){
   console.log("parsing error "+e);
}

console.log("Parsed! " + doc);

3) Setup the needed namespaces:

import { Component, OnInit } from "@angular/core";
import { DOMParser as dom } from "xmldom";
import * as Xpath from "xpath";
import {request} from "http";
import { Item } from "./item";
import { ItemService } from "./item.service";

var result = response.content.toJSON();
try{
   var doc = new dom().parseFromString(result["data"]);
}
catch(e){
   console.log("parsing error "+e);
}
console.log("Parsed! " + doc);
var select = Xpath.useNamespaces({
            "envlp": "http://schemas.xmlsoap.org/soap/envelope/",
   "lg":"http://test.com"
});

4) Search for the needed value or attribute:

import { Component, OnInit } from "@angular/core";
import { DOMParser as dom } from "xmldom";
import * as Xpath from "xpath";
import {request} from "http";
import { Item } from "./item";
import { ItemService } from "./item.service";

var result = response.content.toJSON();
try{
   var doc = new dom().parseFromString(result["data"]);
}
catch(e){
  console.log("parsing error "+e);
}
console.log("Parsed! " + doc);
var select = Xpath.useNamespaces({
   "envlp": "http://schemas.xmlsoap.org/soap/envelope/",
   "lg":"http://test.com"

});

//---------get value---------
try {
   console.log("Result: '" + select("//envlp:Envelope/envlp:Body/lg:login/lg:timestamp/text()", doc) + "'");
} catch(e) {
   console.log("Error getting the value" + e);
}
//---------get Attribute---------
try {
   console.log("Result: '" + select("//envlp:Envelope/envlp:Body/lg:login/lg:short-message/@author", doc) + "'");
} catch(e) {
   console.log("Error getting the value" + e);
}

5) Final result:

import { Component, OnInit } from "@angular/core";
import { DOMParser as dom } from "xmldom";
import * as Xpath from "xpath";
import {request} from "http";
import { Item } from "./item";
import { ItemService } from "./item.service";

@Component({
   selector: "ns-items",
   moduleId: module.id,
   templateUrl: "./items.component.html",
})

export class ItemsComponent implements OnInit {
  items: Item[];
  constructor(private itemService: ItemService) { }
  ngOnInit(): void {
    this.items = this.itemService.getItems();
   }
onTap(args){
   request({
     url: "https://httpbin.org/post",
     method: "POST",
     headers: { "Content-Type": "application/json" },
     content:
    "<?xml version='1.0' encoding='UTF-8'?>"+
    "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' >"+
       "<soapenv:Body>"+
          "<login xmlns='http://test.com'>"+
             "<timestamp >2017-04-22T14:40:57.655Z</timestamp>"+
             "<version >4.2</version>"+
             "<short-message author='J. K. Rowling' >Invalid webservice credentials.</short-message>"+
             "<long-message>Sample xml responce</long-message>"+
          "</login>"+
       "</soapenv:Body>"+
    "</soapenv:Envelope>"
    })
    
    .then(function (response) {
       var result = response.content.toJSON();
       try{
         var doc = new dom().parseFromString(result["data"]);
       }
    catch(e){
       console.log("parsing error "+e);
    }
    console.log("Parsed! " + doc);
    var select = Xpath.useNamespaces({
       "envlp": "http://schemas.xmlsoap.org/soap/envelope/",
       "lg":"http://test.com"
    });

    //---------get value---------
    try {
      console.log("Result: '" + select("//envlp:Envelope/envlp:Body/lg:login/lg:timestamp/text()", doc) + "'");
    } catch(e) {
       console.log("Error getting the value" + e);
    }
    //---------get Attribute---------
    try {
       console.log("Result: '" + select("//envlp:Envelope/envlp:Body/lg:login/lg:short-message/@author", doc) + "'");
    } catch(e) {
       console.log("Error getting the value" + e);
    }
    
    }, function (e) {
       console.log("Error: " +e);
    });
    
    }
}

Note: The important part in the sample code is to setup the correct namespaces for the select method, while using useNamespaces. This method evaluates the provided xpath expression using the XML namespace definitions provided in mapppings.

You can find more information about these plugins in the README files for xpath and xmldom.