We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

Using ServerXMLHTTP to integrate UPS Shipping API with ASP site.  Can't parse 2 XML docs concatenated which is required by UPS.

Medium Priority
3,699 Views
Last Modified: 2013-11-19
OK this is a very specific and lengthy question, so please bear with me.  I am trying to integrate the UPS shipping API with my website (not the rates one, the shipping one you have to actually register for).  The problem is that in order to use the API, UPS requires you to send 2 separate XML documents concatenated together to thier API which they separate and then send back a response to.  I am unable to do this using ServerXMLHTTP and Msxml2.DOMDocument.  Below is the string which I am sending to UPS:

<?xml version="1.0"?>
  <AccessRequest xml:lang="en-US">
   <AccessLicenseNumber><![CDATA[mylicensenumber]]></AccessLicenseNumber>
   <UserId><![CDATA[myuserid]]></UserId>
   <Password><![CDATA[mypassword]]></Password>
  </AccessRequest>
<?xml version="1.0"?>
<ShipmentConfirmRequest xml:lang="en-US">
<Request>
<TransactionReference>
<CustomerContext>ShipConfirmUS</CustomerContext>
<XpciVersion>1.0001</XpciVersion>
</TransactionReference>
<RequestAction>ShipConfirm</RequestAction>
<RequestOption>nonvalidate</RequestOption>
</Request>
<LabelSpecification>
<LabelPrintMethod>
<Code>EPL</Code>
</LabelPrintMethod>
<LabelStockSize>
<Height>4</Height>
<Width>6</Width>
</LabelStockSize>
</LabelSpecification>
<Shipment>
<Shipper>
<Name>ShipperName</Name>
<AttentionName>ShipperAttnName</AttentionName>
<PhoneNumber>
<StructuredPhoneNumber>
<PhoneDialPlanNumber>222626</PhoneDialPlanNumber>
<PhoneLineNumber>7227</PhoneLineNumber>
<PhoneExtension>929</PhoneExtension>
</StructuredPhoneNumber>
</PhoneNumber>
<ShipperNumber>12345E</ShipperNumber>
<Address>
<AddressLine1>22 USShipperAddr1</AddressLine1>
<AddressLine2>USShipperAddr2</AddressLine2>
<AddressLine3>USShipperAddr3</AddressLine3>
<City>Plano</City>
<StateProvinceCode>TX</StateProvinceCode>
<PostalCode>75093</PostalCode>
<CountryCode>US</CountryCode>
</Address>
</Shipper>
<ShipTo>
<CompanyName>ShipToCompanyName</CompanyName>
<AttentionName>ShipToAttnName</AttentionName>
<PhoneNumber>
<StructuredPhoneNumber>
<PhoneDialPlanNumber>333656</PhoneDialPlanNumber>
<PhoneLineNumber>7337</PhoneLineNumber>
<PhoneExtension>9339</PhoneExtension>
</StructuredPhoneNumber>
</PhoneNumber>
<Address>
<AddressLine1>33 ShipToAddr1</AddressLine1>
<AddressLine2>USShipToAddr2</AddressLine2>
<AddressLine3>USShipToAddr3</AddressLine3>
<City>Atlanta</City>
<StateProvinceCode>GA</StateProvinceCode>
<PostalCode>30346</PostalCode>
<CountryCode>US</CountryCode>
<ResidentialAddress/>
</Address>
</ShipTo>
<ShipFrom>
<CompanyName>ShipFromCompanyName</CompanyName>
<AttentionName>ShipFromAttnName</AttentionName>
<PhoneNumber>
<StructuredPhoneNumber>
<PhoneDialPlanNumber>111616</PhoneDialPlanNumber>
<PhoneLineNumber>7117</PhoneLineNumber>
<PhoneExtension>9119</PhoneExtension>
</StructuredPhoneNumber>
</PhoneNumber>
<Address>
<AddressLine1>22 ShipFromAddr1 St</AddressLine1>
<AddressLine2>USShipFromAddr2</AddressLine2>
<AddressLine3>USShipFromAddr3</AddressLine3>
<City>Athens</City>
<StateProvinceCode>GA</StateProvinceCode>
<PostalCode>30605</PostalCode>
<CountryCode>US</CountryCode>
</Address>
</ShipFrom>
<PaymentInformation>
<Prepaid>
<BillShipper>
<AccountNumber>12345E</AccountNumber>
</BillShipper>
</Prepaid>
</PaymentInformation>
<Service>
<Code>01</Code>
</Service>
<ShipmentServiceOptions>
<Notification>
<EMailMessage>
<EMailAddress>christy@company1.com</EMailAddress>
<Memo>EmailShipNot Memo</Memo>
</EMailMessage>
</Notification>
<Notification>
<EMailMessage>
<EMailAddress>joe@company2.com</EMailAddress>
UPS ONLINE TOOLS
<NotificationCode>6</NotificationCode>
</EMailMessage>
</ShipmentNotification>
</ShipmentServiceOptions>
<Package>
<PackagingType>
<Code>03</Code>
</PackagingType>
<PackageWeight>
<UnitOfMeasurement>
<Code>LBS</Code>
</UnitOfMeasurement>
<Weight>2</Weight>
</PackageWeight>
</Package>
<Package>
<PackagingType>
<Code>02</Code>
</PackagingType>
<ReferenceNumber>
<Code>9V</Code>
<Value>abcdefg</Value>
</ReferenceNumber>
<PackageWeight>
<UnitOfMeasurement>
<Code>LBS</Code>
</UnitOfMeasurement>
<Weight>2</Weight>
</PackageWeight>
<PackageServiceOptions>
<COD>
<CODFundsCode>8</CODFundsCode>
<CODCode>3</CODCode>
<CODAmount>
<CurrencyCode>USD</CurrencyCode>
<MonetaryValue>35000</MonetaryValue>
</CODAmount>
</COD>
<InsuredValue>
<CurrencyCode>USD</CurrencyCode>
<MonetaryValue>500.55</MonetaryValue>
</InsuredValue>
</PackageServiceOptions>
</Package>
</Shipment>
</ShipmentConfirmRequest>

I have confirmed this string to be in the correct format for the API.  The page I am using to send the request, and parse the results is as follows (sxml =  string from above):

<%@ LANGUAGE="VBScript" %>
<!--#INCLUDE FILE="Media/commonfunctions.asp"-->
<!--#INCLUDE FILE="Media/UPSFunctions.asp"-->
<%'Option Explicit
      Response.Buffer = true
      Response.ContentType = "text/xml"
      Response.Charset = "iso-8859-1"
      Response.Expires=0
      Response.AddHeader "pragma", "nocache"

'we make API calls using the ServerXMLHTTP object
Dim oXMLHTTP
'we make the actual request by sending a DOM Document
Dim oXMLDoc
'used in parsing example
Dim sOutput
Dim oNode

'Check call type and get appropriate XML
sXML = UPSRequest

'create the objects
Set oHTTPConn = Server.CreateObject("Msxml2.ServerXMLHTTP.3.0")
'the DOM Document to load the request into and send
Set oXMLDoc = Server.CreateObject("Msxml2.DOMDocument.3.0")

'we are going to do a synchronous call and wait for the response
oHTTPConn.open "POST", Application("ShipConfirmURL"), False
'set the HTTP headers
oHTTPConn.setRequestHeader "Content-Type", "text/xml"

response.write sXML
'load the DOM Document synchronously
oXMLDoc.async = False
If (Not oXMLDoc.loadXML(sXML) Or (oXMLDoc.parseError.errorCode <> 0)) Then
      'sanity check on the request BEFORE the request has been made.
    'see the IXMLDOMParseError Members documentation for parseError
    'properties if you want to capture more information
      Response.write "<?xml version=""1.0"" encoding=""iso-8859-1""?><Error><Code>" & oXMLDoc.parseError.errorCode
      Response.write "</Code><LineNumber>" & oXMLDoc.parseError.line & "</LineNumber>"
      Response.write "<Reason>" & oXMLDoc.parseError.reason & "</Reason></Error>"
Else
      oHTTPConn.send oXMLDoc
      'check for errors
      Set oNode = oHTTPConn.responseXML.selectSingleNode("/Error/ErrorCode")
      If (Not oNode Is Nothing) Then
          'the API returned an error
          'process the list of Error nodes
          'this information can be logged and processed
          'however you wish
            Response.write "I Failed"
      Else
      'at this point you can parse the responseXML DOM however you like
      'for example
      
                  response.write oHTTPConn.responseXML.xml
      End If
End If
Set oHTTPConn = Nothing
Set oXMLDoc = Nothing
Set oNode = Nothing
%>

When this code is run, I get an error "Only one top level element is allowed in an XML document." and the pointer is at the next "<?xml version="1.0"?>".  I need someone who has worked with the UPS Shipping API to let me know what I should do I guess.  Thanks in advance!

ED7
Comment
Watch Question

The XML you are sending does not validate as XML. You need to format the XML document so it can validate as XML. Try to open the XML document you are sending in IE - it will give you an error.

If you NEED to send it as formatted above then don't use Server.CreateObject("Msxml2.DOMDocument.3.0") do load the document - because it requires the XML to be valid. If it is a local document the use the File System Object (FSO) to read the file and pass it to XMLHTTP object as a string.

Author

Commented:
Sorry, i dont follow.  The XML I referenced above was copied directly from the UPS Shipping API PDF file and is exactly what they have specified to pass.  There is a blurb in there I don't quite understand and it is as follows:

-Shipping Programming Information Shipping Guidelines-
Each input request is made up of two separate XML request documents. These requests are concatenated
and posted to the UPS web servers using a single HTTP Post.

When validating the request XML documents, do not treat the two concatenated documents as a single XML
document. XML parsers can not parse two concatenated documents. Validate each XML Request separately.
UPS will separate the two documents and parse them individually. To ensure this occurs, verify that
<?xml version="1.0"?> is at the top of each XML request document.

Does that help at all?
CERTIFIED EXPERT
Top Expert 2012

Commented:
>>Sorry, i dont follow. <<
What Sleepyhead_NO is referring to is that your XML document (actually the second one) is not well-formed.  He/she refered to it being invalid, but in order to validate it, it requires a DTD or XML Schema, which it does not have and therefore is a separate issue.

Author

Commented:
Oh well, I copied that xml doc verbatim from the UPS PDF file as thier example.  The spacing and TABs didnt translate, but it is exactly the same as thier example.

ED7
CERTIFIED EXPERT
Top Expert 2012

Commented:
>>Oh well, I copied that xml doc verbatim from the UPS PDF file as thier example. << 
Than all I can say is that someone at UPS does not know XML from a hole in the wall.  

Do yourself a favor and do the following:
1 .Copy and paste the second XML document into your favorite text editor (NotePad ?).  
2. Save it as something.xml
3. Run it in IE (as was previously suggested) and you will get the following error message:

End tag 'ShipmentNotification' does not match the start tag 'Notification'. Error processing resource 'file:///C:/Temp/Temp1.xml'. Line 106, Position 3

</ShipmentNotification>
--^

4. Change in your text editor:
</ShipmentNotification>
To:
</Notification>

5. Save it.
6. Re-run it in IE and it will display something like this:
<?xml version="1.0"?>
<ShipmentConfirmRequest xml:lang="en-US">
      <Request>
            <TransactionReference>
                  <CustomerContext>ShipConfirmUS</CustomerContext>
                  <XpciVersion>1.0001</XpciVersion>
            </TransactionReference>
            <RequestAction>ShipConfirm</RequestAction>
            <RequestOption>nonvalidate</RequestOption>
      </Request>
      <LabelSpecification>
            <LabelPrintMethod>
                  <Code>EPL</Code>
            </LabelPrintMethod>
            <LabelStockSize>
                  <Height>4</Height>
                  <Width>6</Width>
            </LabelStockSize>
      </LabelSpecification>
      <Shipment>
            <Shipper>
                  <Name>ShipperName</Name>
                  <AttentionName>ShipperAttnName</AttentionName>
                  <PhoneNumber>
                        <StructuredPhoneNumber>
                              <PhoneDialPlanNumber>222626</PhoneDialPlanNumber>
                              <PhoneLineNumber>7227</PhoneLineNumber>
                              <PhoneExtension>929</PhoneExtension>
                        </StructuredPhoneNumber>
                  </PhoneNumber>
                  <ShipperNumber>12345E</ShipperNumber>
                  <Address>
                        <AddressLine1>22 USShipperAddr1</AddressLine1>
                        <AddressLine2>USShipperAddr2</AddressLine2>
                        <AddressLine3>USShipperAddr3</AddressLine3>
                        <City>Plano</City>
                        <StateProvinceCode>TX</StateProvinceCode>
                        <PostalCode>75093</PostalCode>
                        <CountryCode>US</CountryCode>
                  </Address>
            </Shipper>
            <ShipTo>
                  <CompanyName>ShipToCompanyName</CompanyName>
                  <AttentionName>ShipToAttnName</AttentionName>
                  <PhoneNumber>
                        <StructuredPhoneNumber>
                              <PhoneDialPlanNumber>333656</PhoneDialPlanNumber>
                              <PhoneLineNumber>7337</PhoneLineNumber>
                              <PhoneExtension>9339</PhoneExtension>
                        </StructuredPhoneNumber>
                  </PhoneNumber>
                  <Address>
                        <AddressLine1>33 ShipToAddr1</AddressLine1>
                        <AddressLine2>USShipToAddr2</AddressLine2>
                        <AddressLine3>USShipToAddr3</AddressLine3>
                        <City>Atlanta</City>
                        <StateProvinceCode>GA</StateProvinceCode>
                        <PostalCode>30346</PostalCode>
                        <CountryCode>US</CountryCode>
                        <ResidentialAddress/>
                  </Address>
            </ShipTo>
            <ShipFrom>
                  <CompanyName>ShipFromCompanyName</CompanyName>
                  <AttentionName>ShipFromAttnName</AttentionName>
                  <PhoneNumber>
                        <StructuredPhoneNumber>
                              <PhoneDialPlanNumber>111616</PhoneDialPlanNumber>
                              <PhoneLineNumber>7117</PhoneLineNumber>
                              <PhoneExtension>9119</PhoneExtension>
                        </StructuredPhoneNumber>
                  </PhoneNumber>
                  <Address>
                        <AddressLine1>22 ShipFromAddr1 St</AddressLine1>
                        <AddressLine2>USShipFromAddr2</AddressLine2>
                        <AddressLine3>USShipFromAddr3</AddressLine3>
                        <City>Athens</City>
                        <StateProvinceCode>GA</StateProvinceCode>
                        <PostalCode>30605</PostalCode>
                        <CountryCode>US</CountryCode>
                  </Address>
            </ShipFrom>
            <PaymentInformation>
                  <Prepaid>
                        <BillShipper>
                              <AccountNumber>12345E</AccountNumber>
                        </BillShipper>
                  </Prepaid>
            </PaymentInformation>
            <Service>
                  <Code>01</Code>
            </Service>
            <ShipmentServiceOptions>
                  <Notification>
                        <EMailMessage>
                              <EMailAddress>christy@company1.com</EMailAddress>
                              <Memo>EmailShipNot Memo</Memo>
                        </EMailMessage>
                  </Notification>
                  <Notification>
                        <EMailMessage>
                              <EMailAddress>joe@company2.com</EMailAddress>
                              UPS ONLINE TOOLS
                              <NotificationCode>6</NotificationCode>
                        </EMailMessage>
                  </Notification>
            </ShipmentServiceOptions>
            <Package>
                  <PackagingType>
                        <Code>03</Code>
                  </PackagingType>
                  <PackageWeight>
                        <UnitOfMeasurement>
                              <Code>LBS</Code>
                        </UnitOfMeasurement>
                        <Weight>2</Weight>
                  </PackageWeight>
            </Package>
            <Package>
                  <PackagingType>
                        <Code>02</Code>
                  </PackagingType>
                  <ReferenceNumber>
                        <Code>9V</Code>
                        <Value>abcdefg</Value>
                  </ReferenceNumber>
                  <PackageWeight>
                        <UnitOfMeasurement>
                              <Code>LBS</Code>
                        </UnitOfMeasurement>
                        <Weight>2</Weight>
                  </PackageWeight>
                  <PackageServiceOptions>
                        <COD>
                              <CODFundsCode>8</CODFundsCode>
                              <CODCode>3</CODCode>
                              <CODAmount>
                                    <CurrencyCode>USD</CurrencyCode>
                                    <MonetaryValue>35000</MonetaryValue>
                              </CODAmount>
                        </COD>
                        <InsuredValue>
                              <CurrencyCode>USD</CurrencyCode>
                              <MonetaryValue>500.55</MonetaryValue>
                        </InsuredValue>
                  </PackageServiceOptions>
            </Package>
      </Shipment>
</ShipmentConfirmRequest>

This tells you it is now a well-formed XML document, which you can open with MSXML
CERTIFIED EXPERT
Top Expert 2012
Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION

Author

Commented:
Yes you are right...typo on my part.  But even when it is well formed, I still need help with my original question.  Thanks.
CERTIFIED EXPERT
Top Expert 2012

Commented:
Also, regarding these two old open questions:

1 02/09/2004 125 What determines the order of a querystri...  Open Active Server Pages (ASP)
2 03/04/2004 250 Problem with displaying XML on server? (...  Open XML

Please see this:
Request a refund because you answered your own question (Refund/PAQ) https://www.experts-exchange.com/help.jsp#hi70
Request a refund because no one answered your question (Delete) https://www.experts-exchange.com/help.jsp#hi71
"But even when it is well formed, I still need help with my original question.  Thanks."

What is your question? Do you still get the same error?
CERTIFIED EXPERT
Top Expert 2012

Commented:
Sleepyhead_NO,

I think my message and the questioner's crossed.  I had already answered regarding how to concatenate two XML documents.

Author

Commented:
I guess I just dont understand how I am supposed to submit a concatenated xml doc to UPS?  Can anyone give me specific code for doing this using my 2 xml docs as an example?  I thought I could concatenate it by just doing an xml = doc1 & doc2 and just use DomDocument to submit that string to UPS, but that doesnt work.  I just need an example I guess.  Thanks.

ED7
CERTIFIED EXPERT
Top Expert 2012

Commented:
Let's try that once again (since you have now resolved the second XML document):

oHTTPConn.send oXMLDoc1.xml & oXMLDoc2.xml
CERTIFIED EXPERT
Top Expert 2012

Commented:
So that this is crystal clear:

You never submit (under any circumstance) an XML document using the Send method (oHTTPConn.send oXMLDoc), you instead submit a string representation of an XML document (oHTTPConn.send oXMLDoc.xml)

Author

Commented:
sorry acperkins, I must have replied at the same time you were posting your answer.  Let me try your example and see what I come up with.  Thanks.

ED7

Author

Commented:
OK I changed my oHTTPConn.send to send (oXMLDoc.xml & oXMLDoc2.xml) after loading both variables with the correct string, and now I get the following message:

XML document must have a top level element. Error processing resource

When I send the second one individually, I get a UPS specific error, so I know it is working correctly.  When I send just the AccessRequest one individually, I get the same error as when I send them both togther.  The string I am loading into oXMLDoc is as follows:

  <?xml version="1.0" ?>
    <AccessRequest xml:lang="en-US">
       <AccessLicenseNumber><![CDATA[ mylicense]]></AccessLicenseNumber>
      <UserId><![CDATA[ myuserid]]></UserId>
      <Password><![CDATA[ mypassword]]></Password>
    </AccessRequest>

Which seems correct to me, but I am a newbie to XML.  Thanks again in advance.

ED7
CERTIFIED EXPERT
Top Expert 2012

Commented:
I suspect this is your problem:
Response.ContentType = "text/xml"

You are indicating you are sending xml when in fact you are not.

Author

Commented:
ACperkins, you are the mack..it now works, but it returns the xml in one giant string...how do I get it so it displays as an XML document on my screen?  This is the source of the page, but it is just one continuous string on the screen, and I want it to display as an xml page so each node can be compacted or expanded:

<?xml version="1.0"?>
<ShipmentConfirmResponse><Response><TransactionReference><CustomerContext>ShipConfirmUS</CustomerContext><XpciVersion>1.0001</XpciVersion></TransactionReference><ResponseStatusCode>1</ResponseStatusCode><ResponseStatusDescription>Success</ResponseStatusDescription></Response><ShipmentCharges><TransportationCharges><CurrencyCode>USD</CurrencyCode><MonetaryValue>3.92</MonetaryValue></TransportationCharges><ServiceOptionsCharges><CurrencyCode>USD</CurrencyCode><MonetaryValue>0.00</MonetaryValue></ServiceOptionsCharges><TotalCharges><CurrencyCode>USD</CurrencyCode><MonetaryValue>3.92</MonetaryValue></TotalCharges></ShipmentCharges><BillingWeight><UnitOfMeasurement><Code>LBS</Code></UnitOfMeasurement><Weight>5.0</Weight></BillingWeight><ShipmentIdentificationNumber>1ZRW18250392418869</ShipmentIdentificationNumber><ShipmentDigest>VERY LARGE STRING</ShipmentDigest></ShipmentConfirmResponse>

Thanks and I will be awarding you the pts!

Ed7
CERTIFIED EXPERT
Top Expert 2012

Commented:
>>how do I get it so it displays as an XML document on my screen?<<
You can, but why would you want to.  It makes more sense, to grab the individual pieces of information that you are looking for using XPath and
present it in a readable format.  However if you insist, use this code:

Dim XmlResponse
Dim XslResponse
Set XmlResponse = oHTTPConn.responseXML
Set XslResponse = Server.CreateObject("MSXML2.DOMDocument")
If XslResponse.Load("res://msxml3.dll/defaultss.xsl") Then
         Response.Write XmlResponse.transformNode(DefaultXSL)
Else
      Response.Write "XSL: " & XslResponse.parseError.Reason
End If
Set XslResponse = Nothing
Set XmlResponse = Nothing

This will present it as if you had saved the response in an XML file and opened it in IE

Author

Commented:
Yes you are right, that makes much more sense....the points are yours!  Thanks

ED7
We are also trying to integrate the UPS API using ASP classic into our website and was wondering what you eventually worked out? I tried to follow the thread but can't seem to get it working.

Author

Commented:
Wow, it has been years since we did this, but we eventually got it working and used it for years. I will look for the old code.
CERTIFIED EXPERT
Top Expert 2012

Commented:
>>Wow, it has been years since we did this<<
5 years to be precise. :)
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.