JD Long
JD Long

Reputation: 60746

Parsing XML with namespace in google apps script

I'm trying to parse XML from SportsRadar api and retrieve info about medals per country for the Olympics. The API seems to be using namespaces and I can't quite figure out how to parse the XML.

If I look at the top of the XML it looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<medals xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.sportradar.com/sportsapi/v1/winterolympics" generated_at="2017-12-03T12:23:38+01:00" xsi:schemaLocation="http://schemas.sportradar.com/sportsapi/v1/winterolympics http://schemas.sportradar.com/bsa/winterolympics/v1/xml/endpoints/winterolympics/medals.xsd">
  <medals_by_country>
    <medal_info country="Slovenia" country_code="SLO" ioc_code="SLO" total_ranking="1" gold_ranking="1" total="24" gold="14" silver="3" bronze="7"/>
    <medal_info country="Canada" country_code="CAN" ioc_code="CAN" total_ranking="2" gold_ranking="1" total="17" gold="9" silver="5" bronze="3"/>
    <medal_info country="Germany" country_code="GER" ioc_code="GER" total_ranking="3" gold_ranking="1" total="19" gold="8" silver="6" bronze="5"/>

And if I get the root element and look at the children, I use this code:

var xml_root = xmlData.getRootElement()
Logger.log( xml_root.getChildren() )

and get this output:

[18-02-10 15:29:52:056 EST] [[Element: <medals_by_country [Namespace: http://schemas.sportradar.com/sportsapi/v1/winterolympics]/>], [Element: <medals_by_sport [Namespace: http://schemas.sportradar.com/sportsapi/v1/winterolympics]/>]]

So looking at the docs it seems like getChildText(name, namespace) should be my magic ticket to get the medals by country info. So I try:

var tst = xml_root.getChildText('medals_by_country', 'http://schemas.sportradar.com/sportsapi/v1/winterolympics');

but I get an error telling me "Cannot find method getChildText(string,string)". I'm parsing that to mean that the namespace should not be passed as a string, maybe? But I can't figure out what it should be passed as.

I tried just grabbing the first country info by doing:

xml_root.getChild('medals_by_country').getChildren('medal_info');

And xml_root.getChild('medals_by_country') returns null. I presume this is because I'm not referencing it by namespace...

So what should I be doing in order to get the medal info for each country? It feels like I'm close but there's something I'm not groking here.

EDIT: I figured out how to create a namespace (I think). I did the following

var ns = XmlService.getNamespace("xsi", "http://schemas.sportradar.com/sportsapi/v1/winterolympics");

Buuut... I'm still pulling nulls from the xml, much to my chagrin.

Upvotes: 0

Views: 1167

Answers (1)

Tanaike
Tanaike

Reputation: 201388

How about this sample script? In this script, your xml data was tested as a sample data. For this, I added </medals_by_country></medals> at the end of xml. Values of medal_info can be retrieved by getAttributes().

Sample script :

function myFunction(){
  var xml = '<?xml version="1.0" encoding="UTF-8"?><medals xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.sportradar.com/sportsapi/v1/winterolympics" generated_at="2017-12-03T12:23:38+01:00" xsi:schemaLocation="http://schemas.sportradar.com/sportsapi/v1/winterolympics http://schemas.sportradar.com/bsa/winterolympics/v1/xml/endpoints/winterolympics/medals.xsd"><medals_by_country><medal_info country="Slovenia" country_code="SLO" ioc_code="SLO" total_ranking="1" gold_ranking="1" total="24" gold="14" silver="3" bronze="7"/><medal_info country="Canada" country_code="CAN" ioc_code="CAN" total_ranking="2" gold_ranking="1" total="17" gold="9" silver="5" bronze="3"/><medal_info country="Germany" country_code="GER" ioc_code="GER" total_ranking="3" gold_ranking="1" total="19" gold="8" silver="6" bronze="5"/></medals_by_country></medals>';
  var xmlData = XmlService.parse(xml);
  var xml_root = xmlData.getRootElement();
  var res = [];
  var c1 = xml_root.getChildren();
  for (var i in c1) {
    var c2 = c1[i].getChildren();
    for (var j in c2) {
      var c3 = c2[j].getAttributes();
      var temp = {};
      for (var k in c3) {
        temp[c3[k].getName()] = c3[k].getValue();
      }
      res.push(temp);
    }
  }
  Logger.log(JSON.stringify(res))
}

Result :

[
    {
        "country": "Slovenia",
        "country_code": "SLO",
        "ioc_code": "SLO",
        "total_ranking": "1",
        "gold_ranking": "1",
        "total": "24",
        "gold": "14",
        "silver": "3",
        "bronze": "7"
    },
    {
        "country": "Canada",
        "country_code": "CAN",
        "ioc_code": "CAN",
        "total_ranking": "2",
        "gold_ranking": "1",
        "total": "17",
        "gold": "9",
        "silver": "5",
        "bronze": "3"
    },
    {
        "country": "Germany",
        "country_code": "GER",
        "ioc_code": "GER",
        "total_ranking": "3",
        "gold_ranking": "1",
        "total": "19",
        "gold": "8",
        "silver": "6",
        "bronze": "5"
    }
]

Reference :

If I misunderstand your question, I'm sorry.

Upvotes: 1

Related Questions