1

How would I go about using the BuildRowsetFromXML function to parse a SOAP API Response that contains namespaces.

The examples that I've seen that use BuildRowsetFromXML use it for parsing a more simplified xml structure (//rss/channel/item/title) without namespaces or metadata.

I have the following source code below it outputs the value of the string representation for the status of the HTTP request as well as an attempts to parse the 'Description' attribute of the Holiday names web service.

1) The trouble I am having is I can't seem to figure out how to properly reference the nested tree in the soap:body. In most examples where I see BuildRowsetFromXML function being used to reference the nested elements of choice by designated the ( //soap/GetHolidaysAvailableResponse/GetHolidaysAvailableResult/[@i]/
HolidayCode/Description) as the root folder and accessing each subfolder in a manner similar to this but I get an error when I attempt this I get a row count of '0' so I am sure I am not accurately traversing the tree.

2) The other puzzling thing about this is when i set the content type to be 'text/xml' I am actually expected to see the brackets appearing as text in the callstatus string but I instead I just see the values jumbled together as one large string. Why would that be the case? Why wouldn't I see this as true xml and what do I need to do to make it appear so? I already tried setting the 'content type' to be 'application/xml' but that generated an 415 error for 'unsupported content media type'.

Can anyone provide a explanation of where I need to focus attention for a solution?

%%[
    var @payload,@endpoint,@callstatus,@callresponse, @httppost, @xml, @i, 
    @j, @names, @talents, @talent, @rowCount1, @rowCount2

    set @endpoint = 
   'http://www.holidaywebservice.com//HolidayService_v2/HolidayService2.asmx?wsdl'  
    set @payload = '
    <soapenv:Envelope 
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:hs="http://www.holidaywebservice.com/HolidayService_v2/">
    <soapenv:Body>
    <hs:GetHolidaysAvailable>
    <hs:countryCode>UnitedStates</hs:countryCode>
    </hs:GetHolidaysAvailable>
    </soapenv:Body>
    </soapenv:Envelope>'

    set @httppost = HTTPPost2(@endpoint,'text/xml', @payload, false, 
    @callstatus, @callresponse)=%%

    set @names = 
    BuildRowsetFromXML(@callstatus,
    "//soap/GetHolidaysAvailableResponse/GetHolidaysAvailableResult/[@i]/           
    HolidayCode/Description",1)
    set @rowCount1 = RowCount(@names)

    outputline(concat("<br>rowCount1: ",@rowCount1))
       for @i = 1 to @rowCount1 do

       Set @name = Field(Row(@names,@i), "Value")
       outputline(concat("<br><br>Description: ",@name))

    next @i

 ]%%
  • Shooting from the hip, but shouldn't the BuildRowsetFromXML be looking at @callresponse, not @callstatus? Also, I think it should be CONCAT('//soap/GetHolidaysAvailableResponse/GetHolidaysAvailableResult/[', @i, ']/HolidayCode/Description') - and finally - should it be ...Result/[@i]/ or should it be ...Result[@i]/? I don't see a sample of your XML that you are using the BuildRowsetFromXML on, so I am not sure on paths. – Gortonington Nov 19 '18 at 22:41
2

I discovered that I needed to strip out all of the namespaces as well as the 'xmlns' attributes in order to get the BuildRowsetFromXML to successfully parse it. I see this function working for custom xml attributes so my guess is it has to do with the presence of colons and slashes found within the xmlns attributes that make this necessary. Here is the source code below.

%%[

var @displayXML, @payload, @endpoint, @callstatus, @callresponse, @httppost, 
@i, @path, @nodes, @rowCount, @nodepath, @holidayName

set @endpoint = 
'http://www.holidaywebservice.com//HolidayService_v2/HolidayService2.asmx?wsdl'  
set @payload = ""
set @payload = concat(@payload, '<soapenv:Envelope 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:hs="http://www.holidaywebservice.com/HolidayService_v2/">')
set @payload = concat(@payload, '<soapenv:Body>')
set @payload = concat(@payload, '<hs:GetHolidaysAvailable>')
set @payload = concat(@payload, 
'<hs:countryCode>UnitedStates</hs:countryCode>')
set @payload = concat(@payload, '</hs:GetHolidaysAvailable>')
set @payload = concat(@payload, '</soapenv:Body>')
set @payload = concat(@payload, '</soapenv:Envelope>')

set @httppost = HTTPPost2(@endpoint,'text/xml', @payload, false, @callstatus, 
@callresponse)

set @displayXML = Replace(@callstatus,'<?xml version="1.0" encoding="utf-8"? 
>','')
set @displayXML = Replace(@displayXML,':Body','')
set @displayXML = Replace(@displayXML,':Envelope','')
set @displayXML = Replace(@displayXML,' 
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"','')
set @displayXML = Replace(@displayXML,' 
xmlns="http://www.holidaywebservice.com/HolidayService_v2/"','')
set @path = "/soap/soap/GetHolidaysAvailableResponse/GetHolidaysAvailableResult/HolidayCode"
set @nodes = 
BuildRowsetFromXML(@displayXML,@path,0)
set @rowCount = RowCount(@nodes)

if @rowCount > 0 then

for @i = 1 to @rowCount do

set @nodepath = concat(@path,"[",@i,"]/")

   if rowcount(BuildRowsetFromXML(@displayXML,concat(@nodepath,       
     "Code"))) 
     > 0 then
     set @holidayName = 
     Field(Row(BuildRowsetFromXML(@displayXML,concat(@nodepath,
     "Code"),0),1), 'Value')
     Output(concat("<br>US Holiday Name: ",@holidayName))
   endif

next @i

endif

]%%

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.