How to parse xml in Angular 2
Asked Answered
R

2

19

I'm using an API that uses XML instead of JSON. Any suggestions on how to convert the following XML to JSON or how to properly use the data in an ngFor directive?

Also, would an observable be appropriate here?

<case-file>
  <serial-number>123456789</serial-number>
    <transaction-date>20150101</transaction-date>
      <case-file-header>
       <filing-date>20140101</filing-date>
      </case-file-header>
 // ...
   <classifications>
  <classification>
   <international-code-total-no>1</international-code-total-no>
   <primary-code>025</primary-code>
  </classification>
 </classifications>
 </case-file>
 <case-file>
     <serial-number>234567890</serial-number>
    <transaction-date>20160401</transaction-date>
      <case-file-header>
       <filing-date>20160401</filing-date>
      </case-file-header>
//...
   <classifications>
  <classification>
   <international-code-total-no>1</international-code-total-no>
   <primary-code>042</primary-code>
  </classification>
 </classifications>
</case-file>

export class apiService {
   constructor (private http: Http) {}

   private _apiUrl = 'app/api';  

   getCaseFile () {
     return this.http.get(this._apiUrl)
//conversion to JSON here?
                    .map(res => <CaseFile[]> res.json().data)
                     .catch(this.handleError);
   }
    private handleError (error: Response) {

     console.error(error);
    return Observable.throw(error.json().error || 'Server error');
   }
 }

<div *ngFor="#cf of case-file">{{case-file.serial-number}}</div>
Razor answered 2/4, 2016 at 2:9 Comment(3)
There are several xml to json libraries out thereRoberge
@Roberge I'd welcome recommendations. I'm not aware of any for Angular 2.Razor
No need for an angular2 one, it's not related to components or any angular related thing, just need to convert xml to json and then use angular with that: #1774050Roberge
S
13

Based on the library http://goessner.net/download/prj/jsonxml/, I implemented a sample to receive XML data and parse them into an Angular2 application:

var headers = new Headers();
(...)
headers.append('Accept', 'application/xml');

return this.http.get('https://angular2.apispark.net/v1/companies/', {
  headers: headers
}).map(res => JSON.parse(xml2json(res.text(),'  ')));

To be able to use the library, you need to parse first the XML string:

var parseXml;

if (typeof window.DOMParser != "undefined") {
  parseXml = function(xmlStr) {
    return ( new window.DOMParser() ).parseFromString(xmlStr, "text/xml");
  };
} else if (typeof window.ActiveXObject != "undefined" &&
   new window.ActiveXObject("Microsoft.XMLDOM")) {
    parseXml = function(xmlStr) {
      var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
      xmlDoc.async = "false";
      xmlDoc.loadXML(xmlStr);
      return xmlDoc;
  };
} else {
  throw new Error("No XML parser found");
}

See this question:

See this plunkr: https://plnkr.co/edit/dj63ASQAgrNcLLlwyAum?p=preview.

Scrutable answered 2/4, 2016 at 6:37 Comment(9)
Thank you, I'll give this a try. For some reason, though, the plunkr isn't working for me.Razor
What do you mean by some reason? In fact you need to click on the "test" label ;-)Scrutable
When I click on the "Test" label, nothing happens. The DevTools console shows an error: GET https://angular2.apispark.net/v1/companies/ 401 (Unauthorized)Razor
It works on my side... Do you have the line this.createAuthorizationHeader(headers); in the getCompanies method? You have the credentials in it...Scrutable
Can you see the Authorization header in the request in the dev tools console?Scrutable
Everything seems to be working now. I'm not sure if this should be a comment or a new question on SO, but is there an easy way to ignore the xml prefixes? e.g., if it was <com: case-file> instead of just <case-file> can I just ignore the com prefix?Razor
I know this is old but I'm getting "Cannot find name xml2json"Buckle
getting the same "Cannot find name xml2json" after adding the sml2json.js file in the project also. and adding the path of file in the index.html file also.Isogonic
Why this answer is the solution? Working with Angular doesn't mean you can use ActiveXObject. It won't work with no other navigator than Internet Explorer, right?Watersick
P
3

I would rather go with npm module instead of Javascript because

  1. This is TypeScript & not JavaScript
  2. while serving this would work, but while making a build or distribution it wont work as it will give error xml2json is not defined as it is available only in javascript & Not in TS or at the time of transpilation.(happened in my case)

I did something like this.

var parser = new xml2js.Parser({explicitArray : false});
//used xml2js parser from npm (https://www.npmjs.com/package/xml2js)
//and in my service i used this 
this.http.get(this.newsURL)
                .flatMap(res=>{
                        return Observable.fromPromise(this.getJSON(res.text()))
                })
                .catch((error:any) => Observable.throw(error.json().error || 'Server error'));
Piwowar answered 18/12, 2016 at 9:38 Comment(1)
Can you write the implementation of this.getJSON method and error.jsonDagley

© 2022 - 2024 — McMap. All rights reserved.