Tulip Connectors can be used to interact with many types of external data sources. This article focuses on HTTP APIs that exchange information using XML. This category includes SOAP APIs.

Sending XML Data in Tulip

To send XML content in the body of a request, use the $value$ notation to show that a parameter should be inserted.

For example, with the following in the Request Body field:

<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:mes="http://mes.myexample.com"
xmlns:get="http://getInfo.mes.myexample.com"
>
<soapenv:Header/>
<soapenv:Body>
<mes:getInfo>
<mes:in0>
<get:value1>$input1$</get:value1>
<get:value2>$input2$</get:value2>
</mes:in0>
</mes:getInfo>
</soapenv:Body>
</soapenv:Envelope>

and the values input1 and input2 as inputs to the Connector Function, a request is made with the values of input1 and input2 substituted into the Request Body.

This is shown in the Tulip Connector Function interface below:

Parsing XML Data in Tulip

A Simple API Example

Let's start with a simple example response from an XML API.

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book category="cooking">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="children">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="web">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>

The following examples show how to access the various pieces of information within Tulip.

An extractor of:

/bookstore/book[1]/title

returns:

<title lang="en">Everyday Italian</title>

Note that arrays in XML are "1-indexed", meaning that the first element is in the "1" position, as opposed to json-query which is "0-indexed".

An extractor of:

/bookstore/book[1]/title/text()

returns:

Everyday Italian

Note that the /text() function is used to extract the text value contained within the selected node.

An extractor of:

/bookstore/book[@category="children"][1]/title/text()

returns:

Harry Potter

Note that the selector has allowed us to search within the properties of a node.

These examples can be directly used in Tulip as shown below:

A SOAP API Example

Now let's examine a more complex case with namespaces, a typical feature of SOAP APIs.

<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
<soap:Body>
<ns1:getInfoResponse xmlns:ns1="http://mes.myexample.com">
<ns1:out>
<errorCode xmlns="http://getInfo.mes.myexample.com">
0
</errorCode>
<errorMessage xmlns="http://getInfo.mes.myexample.com">
info retrieved successfully
</errorMessage>
<unitInfos xmlns="http://getInfo.mes.myexample.com">
<Info>
<currentOperation>My Operation</currentOperation>
<nextOperation>None</nextOperation>
<partName>1234567-890</partName>
<partRevision>B</partRevision>
<previousOperation xsi:nil="true"/>
<properties>
<Property>
<propertyName>PartNumber</propertyName>
<propertyValue>1234567-890</propertyValue>
</Property>
<Property>
<propertyName>PartRevision</propertyName>
<propertyValue>B</propertyValue>
</Property>
<Property>
<propertyName>PartDescription</propertyName>
<propertyValue>My example part</propertyValue>
</Property>
</properties>
<queueName xsi:nil="true"/>
<state>Normal</state>
</Info>
</unitInfos>
</ns1:out>
</ns1:getInfoResponse>
</soap:Body>
</soap:Envelope>

This response uses XML Namespaces, which add complexity. For most cases, a global search using the //* and .//* operators makes extraction very simple.

An extractor of:

//*[local-name()="propertyName"][1]/text()

returns:

PartNumber

Note again that arrays in XML are "1-indexed", meaning that the first element is in the "1" position, as opposed to json-query which is "0-indexed".

An extractor of:

//*[local-name()="Property"]

returns:

<Property xmlns="http://getInfo.mes.myexample.com">
<propertyName>PartNumber</propertyName>
<propertyValue>1234567-890</propertyValue>
</Property>
<Property xmlns="http://getInfo.mes.myexample.com">
<propertyName>PartRevision</propertyName>
<propertyValue>B</propertyValue>
</Property>
<Property xmlns="http://getInfo.mes.myexample.com">
<propertyName>PartDescription</propertyName>
<propertyValue>My example part</propertyValue>
</Property>

Note here that the namespaces are "brought down" into this result. And therefore a sub-query would still search the global namespace.

To extract an array of objects, use the global search shown in the previous example to extract the array, and then a local search extractor of:

.//*[local-name()="propertyName"]/text()

to retrieve an array of objects of the form:

[
{
"Name": "PartNumber"
"Value": "1234567-890"
},
{
"Name": "PartRevision"
"Value": "B"
},
{
"Name": "PartDescription"
"Value": "My example part"
}
]

These examples are shown in the Tulip Connectors Interface below:

Did this answer your question?