0

I've seen that this problem is fairly common across Angular 2, but I haven't seen anything that helps with my particular situation.

Specifically, I'm creating an app that's pulling data from an API (which requires an API key), where the results are specifically in XML format. What I'm trying to do is call the API when a user enters search parameters, have the API return the results, and then eventually display the results on the same screen.

However, I keep encountering the same "Unexpected token <" error, where the source of the error is on the URL of the API itself. I have my suspicion that the problem is stemming from the fact that I'm attempting to return the body as JSON, but I've never experienced this problem before so I was hoping the community could help!

Here's my Service and Component code below:

search-bar.component.ts

import { Component, Output, Input, EventEmitter } from '@angular/core';
import { NgForm } from '@angular/forms';
import { NgModel } from '@angular/forms';
import { Observable } from 'rxjs/Observable';

import { Search } from './search';
import { ZillowSearchService } from './zillow-search.service';


@Component({
    moduleId: module.id,
    selector: 'search-bar',
    templateUrl: `search-bar.component.html`,
    styles: [
        `input {
            width: 50%;
            margin-left: 25%;
            margin-top: 15%;
            color: black;
            height: 40px;
        }
        button {
            border-radius: 5px;
            margin-top: 5%;
            margin-left: 45%;
        }
        `
    ]
})
export class SearchBarComponent {
    getSearchResults: string;
    model = new Search("");
    constructor( private zillowSearchService: ZillowSearchService) {}
    private sub: any;
    public state: string = "" ;
    data: string;

   onSubmit(){
        this.zillowSearchService.searchZillow("New Mexico")
                .subscribe(
                data => console.log(data),
                error => console.log("Error: " + error)
                );
    }
}

zillow-search.service.ts:

import { Inject, Injectable } from '@angular/core';
import { Http, Headers, Response, Jsonp } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import '../rxjs-operators';

import { AppConfig } from './app-config';
import { Search } from './search';

let api = AppConfig.baseUrls.api;
let url = AppConfig.baseUrls.base;

@Injectable() 
export class ZillowSearchService {
  public state: string;
  constructor ( @Inject(Jsonp) private jsonp: Jsonp) {
     //this.http = http;
  }
  protected results: any;

  searchZillow(statevar: any) {
    console.log("Before" + statevar);
    var queryString = url + `?zws-id=${api}&state=${statevar}&callback=JSONP_CALLBACK`;

    return this.jsonp 
          .get(queryString, new Headers({ "Content-type":
"application/xml", "Accept": "application/xml", 
          "Access-Control-Allow-Origin": "*" }))
          .map((res: Response) => res.json())
          //.map(res => console.log("TEST"));
          //.map((res) => {
            //return
          //});;
    }
  }

For some additional details, looking into the Console and Network, I can see that the "type" is listed as script and the initiator is http.umd.js, where it points me to BrowserJsonp.send (if this helps provider any context at all).

Let me know if you'd like for me to include any additional code snippets, and I really appreciate the help and guidance!

durham989
  • 31
  • 5

1 Answers1

0

You mentioned the results are in XML format, but I see this code at the bottom of your service:

    return this.jsonp 
      .get(queryString, new Headers({ "Content-type":
      "application/xml", "Accept": "application/xml", 
      "Access-Control-Allow-Origin": "*" }))
      .map((res: Response) => res.json())
      //.map(res => console.log("TEST"));
      //.map((res) => {
        //return
      //});;
}

I'm not certain that you are able to map the response to json that way -- I think it's actually expecting JSON there from a literal that it would map into a typed object you could use.

So the problem is that you are trying to parse xml as json -- hence the error saying that it can't parse the first "<", as that's not valid json.

You will probably need some sort of xml parser to resolve this -- I would look for a 3rd party library in this case :)

EDIT: To be clear, I think the line:

.map((res: Response) => res.json())

is causing the issue, as it's saying take this input json response and convert it to a usable javascript object -- but it can't parse it, as the response is in XML format.

chrispy
  • 3,552
  • 1
  • 11
  • 19
  • Thanks! Let me try that out. Yeah I figured that this was going to be the root of my problem in some way. Any recommendations for XML parsers or method of implementing the parser itself? – durham989 Jan 14 '17 at 21:58
  • Unfortunately I don't, I haven't needed to query an XML serving endpoint yet :( I think the best thing to do would be to grab a package off npm that converts xml to json, then call that in your map instead :) – chrispy Jan 14 '17 at 22:04
  • Found this, could be worth a shot: http://stackoverflow.com/questions/36368405/how-to-parse-xml-in-angular-2 – chrispy Jan 14 '17 at 22:06
  • Thank you!! Checking this out now, and thanks for the edit identifying the res:Response mapping. Will let you know if this works! – durham989 Jan 14 '17 at 22:11