返回博客首页
← 所有文章

在 NativeScript 中处理来自 SOAP 服务的 XML 响应

2017年5月4日 — 作者 Nikolay Tsonev

在服务返回XML 响应的情况下,您可以同时使用xmldomxpath节点插件来处理请求结果。xmldom 允许您解析接收到的响应。xpath 提供了一种简单的方法来读取文本内容以及使用其名称从 XML 中获取特定属性的值。此解决方案可用于纯 NativeScript 项目和 NativeScript Angular 2 项目。

首先,要使用此解决方案,请运行以下命令安装 xmldom 和 xpath

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

这两个命令将插件作为依赖项保存到项目package.json文件中。

在 NativeScript JavaScript 项目中使用

<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) 发出 HTTP 请求

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) 使用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) 设置所需的命名空间

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) 搜索所需的值或属性

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) 最终结果

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;

在 NativeScript TypeScript 项目中使用

<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) 发出 HTTP 请求

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) 使用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) 设置所需的命名空间

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) 搜索所需的值或属性

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) 最终结果

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);
    });
}

在 NativeScript Angular 项目中使用

<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) 发出 HTTP 请求

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) 使用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) 设置所需的命名空间

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) 搜索所需的值或属性

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) 最终结果

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);
    });
    
    }
}

注意:示例代码中的重要部分是在使用useNamespaces时为 select 方法设置正确的命名空间。此方法使用在映射中提供的 XML 命名空间定义来评估提供的 xpath 表达式。

您可以在xpathxmldom的 README 文件中找到有关这些插件的更多信息。