C# XPath Soap, how to navigate to embedded node - c#

In C#, Asp.Net, I am trying to return the Error node inside of BISearchResponse:
I am able to get the GetWireResult node returned in an XMLNode.
How do I get to the Error node?
<?xml version="1.0" encoding="utf-8" ?>
- <soap:Envelope 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">
- <soap:Body>
- <GetWireResponse xmlns="http://OpenSolutions.com/">
<GetWireResult><?xml version="1.0"?>
<BISearchResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Error xmlns="https://bixg.choicepoint.com/webservices/3.0">
<Message>BI System: Failed to Login</Message>
<Code>536870917</Code>
</Error>
</BISearchResponse>
</GetWireResult>
</GetWireResponse>
</soap:Body>
</soap:Envelope>
My code:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(result);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
nsmgr.AddNamespace("ab", "http://OpenSolutions.com/");
nsmgr.AddNamespace("bg", " https://bixg.choicepoint.com/webservices/3.0");
nsmgr.AddNamespace("xsd", "http://www.w3.org/2001/XMLSchema");
nsmgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
XmlNode xmlnode = xmlDoc.DocumentElement.SelectSingleNode("/soap:Envelope/soap:Body/ab:GetWireResponse", nsmgr);
This works to here.
.
I am adding the xml here, but it is only visible in edit mode.
<?xml version="1.0" encoding="utf-8" ?>
- <soap:Envelope 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">
- <soap:Body>
- <GetWireResponse xmlns="http://OpenSolutions.com/">
<GetWireResult><?xml version="1.0"?> <BISearchResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Error xmlns="https://bixg.choicepoint.com/webservices/3.0"> <Message>BI System: Failed to Login</Message> <Code>536870917</Code> </Error> </BISearchResponse></GetWireResult>
</GetWireResponse>
</soap:Body>
</soap:Envelope>

In debug mode, when you copy this XML, try choose another debug visualizer, e.g. "Text visualizer". You can select it clicking the magnifying glass icon in datatip.
I think your XML looks like:
<?xml version="1.0" encoding="utf-8" ?>
<soap:Envelope 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">
<soap:Body>
<GetWireResponse xmlns="http://OpenSolutions.com/">
<GetWireResult>
<?xml version="1.0"?>
<BISearchResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Error xmlns="https://bixg.choicepoint.com/webservices/3.0">
<Message>BI System: Failed to Login</Message>
<Code>536870917</Code>
</Error>
</BISearchResponse>
</GetWireResult>
</GetWireResponse>
</soap:Body>
</soap:Envelope>
or
<?xml version="1.0" encoding="utf-8" ?>
<soap:Envelope 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">
<soap:Body>
<GetWireResponse xmlns="http://OpenSolutions.com/">
<GetWireResult>
<![CDATA[
<?xml version="1.0"?>
<BISearchResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Error xmlns="https://bixg.choicepoint.com/webservices/3.0">
<Message>BI System: Failed to Login</Message>
<Code>536870917</Code>
</Error>
</BISearchResponse>
]]>
</GetWireResult>
</GetWireResponse>
</soap:Body>
</soap:Envelope>
No matter. So you can select GetWireResult using following XPath:
/soap:Envelope/soap:Body/ab:GetWireResponse/ab:GetWireResult
and then load it content in new XML document and get desired response.

You're almost there. Extend your XPath
"/soap:Envelope/soap:Body/ab:GetWireResponse"
to
"/soap:Envelope/soap:Body/ab:GetWireResponse/ab:GetWireResult/ab:BISearchResponse/bg:Error"
However that extra XML prologue stuck in there in the middle, <?xml version="1.0"?>, makes the XML not well-formed. I'm surprised it can be processed at all. I would think the C# API should throw an exception on xmlDoc.LoadXml(result).
Another approach, seeing as the above does not return anything for you, would be to use your C# code to explore the structure of the XML document and print out the children of each node. E.g. if you are getting a node for "/soap:Envelope/soap:Body/ab:GetWireResponse" but not for "/soap:Envelope/soap:Body/ab:GetWireResponse/ab:GetWireResult", does ab:GetWireResponse have what text node children, and if so, what are their values (contents)? That should give insight into why the XPath is not working.
If there's a block of unparsed (i.e. escaped) XML in there, you could either copy it out and parse it as XML like you said, or just search for the pattern you need using a regexp... depending on the complexity.

Related

remove namespaces, attributes, Xsi from Soap response using code or XSLT

Remove namespaces, attributes, Xsi from Soap response using code or XSLT
Want to transform a soap response to a normal XML(without namespaces, atributes) using C# code (Serializer, XMLDoc, XDoc ) or XSLT.
here is the soap response.
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="urn:Magento"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:catalogProductInfoResponse>
<info xsi:type="ns1:catalogProductReturnEntity">
<product_id xsi:type="xsd:string">3459</product_id>
<sku xsi:type="xsd:string">HK-BP001</sku>
<categories SOAP-ENC:arrayType="xsd:string[0]" xsi:type="ns1:ArrayOfString"/>
<websites SOAP-ENC:arrayType="xsd:string[7]" xsi:type="ns1:ArrayOfString">
<item xsi:type="xsd:string">1</item>
</websites>
<created_at xsi:type="xsd:string">2016-04-19 01:45:35</created_at>
<has_options xsi:type="xsd:string">1</has_options>
<special_from_date xsi:type="xsd:string">2016-04-19 00:00:00</special_from_date>
<tier_price SOAP-ENC:arrayType="ns1:catalogProductTierPriceEntity[0]" xsi:type="ns1:catalogProductTierPriceEntityArray"/>
<custom_design xsi:type="xsd:string">ultimo/default</custom_design>
<enable_googlecheckout xsi:type="xsd:string">1</enable_googlecheckout>
</info>
</ns1:catalogProductInfoResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
i want transformed xml like :
<?xml version="1.0" encoding="UTF-8"?>
<Envelope>
<Body>
<catalogProductInfoResponse>
<info>
<product_id>3459</product_id>
<sku>HK-BP001</sku>
<categories/>
<websites>
<item>1</item>
</websites>
<created_at>2016-04-19 01:45:35</created_at>
<has_options>1</has_options>
<special_from_date>2016-04-19 00:00:00</special_from_date>
<tier_price/>
<custom_design>ultimo/default</custom_design>
<enable_googlecheckout>1</enable_googlecheckout>
</info>
</catalogProductInfoResponse>
</Body>
</Envelope>
You can use XSLT:
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>

missing prefix in soap request c# dynamic web request

I´m using the WsdlImporter to read a wsdl-file and create a dynamic web request. But if I create the request a prefix in my request is missing and the consuming web service can not handle with this request. How can I force, that the prefix will be set?
This is how the request should be:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope 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" xmlns:urn="urn:sap-com:document:sap:rfc:functions>
<soap:Body>
<urn:K23G_GET_COST_ELEMENTS>
<ID_BEKNZ xmlns="">S</ID_BEKNZ>
<ID_COLLECT_MESSAGES xmlns="">X</ID_COLLECT_MESSAGES>
<ID_GJAHR xmlns="">2016</ID_GJAHR>
<ID_KOKRS xmlns="">K001</ID_KOKRS>
<ID_VERSN xmlns="">000</ID_VERSN>
<ID_WRTTP xmlns="">04</ID_WRTTP>
<ET_MESG xmlns="">
<item />
</ET_MESG>
<ET_RESULTS xmlns="">
<item />
</ET_RESULTS>
<IT_COSEL_KSTAR xmlns="">
<item />
</IT_COSEL_KSTAR>
<IT_COSEL_OBJ xmlns="">
<item />
</IT_COSEL_OBJ>
</urn:K23G_GET_COST_ELEMENTS>
</soap:Body>
</soap:Envelope>
An this is how the request looks like:
The urn before K23G_GET_COST_ELEMENTS is missing
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope 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">
<soap:Body>
<K23G_GET_COST_ELEMENTS xmlns:urn="urn:sap-com:document:sap:rfc:functions>
<ID_BEKNZ xmlns="">S</ID_BEKNZ>
<ID_COLLECT_MESSAGES xmlns="">X</ID_COLLECT_MESSAGES>
<ID_GJAHR xmlns="">2016</ID_GJAHR>
<ID_KOKRS xmlns="">K001</ID_KOKRS>
<ID_VERSN xmlns="">000</ID_VERSN>
<ID_WRTTP xmlns="">04</ID_WRTTP>
<ET_MESG xmlns="">
<item />
</ET_MESG>
<ET_RESULTS xmlns="">
<item />
</ET_RESULTS>
<IT_COSEL_KSTAR xmlns="">
<item />
</IT_COSEL_KSTAR>
<IT_COSEL_OBJ xmlns="">
<item />
</IT_COSEL_OBJ>
</urn:K23G_GET_COST_ELEMENTS>
</soap:Body>
</soap:Envelope>
Somebody there who can help me?
Thank you

SOAP fault message

I have to send a SOAP fault message over HTTP to another web service if something goes wrong with a server, so I have this code:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<Response status="1">
<Description>DESC</Description>
<Errors>
<Error>500</Error>
</Errors>
</Response>
</soapenv:Body>
</soapenv:Envelope>
Is this a properly formatted SOAP fault message?
Is this a properly formatted SOAP fault message?
No it isn't. It should look something like this:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>...</faultcode>
<faultstring>...</faultstring>
<detail>...</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>
The SOAP specification specifies what a fault is. Yours looks like an error result object of some sort which has some disadvantages as explained here for example.
Your WS framework should properly generate faults if you throw exceptions. If you are not using a framework but building the fault in some other way, then it must look like in my example above or it can't be called a SOAP fault.
Hey Bogdan I wrote this code and works like a charm!
<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>
<soap:Fault>
<faultcode>500</faultcode>
<faultstring>SERVER ERROR</faultstring>
<detail>
<Response_status>1</Response_status>
<Description>DESCRIPTION</Description>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>
But another question how to send a SOAP success message with a http code 200 an also I have to have some additional parameters in the message, this is a part of it
<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>
<Response_status>0</Response_status>
<Description>SUCCESS</Description>
</soap:Body>
</soap:Envelope>
So with this also I have to send code 200, how to write that can I write it like this
<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>
<soap:Fault>
<faultcode>200</faultcode>
<faultstring>OK</faultstring>
<detail>
<Response_status>0</Response_status>
<Description>SUCCESS</Description>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>

Reading different XML with C#/DOM

I am currently using DOM to navigate xml in my C# project. However, some XML that i've come across lately is a bit different.
whereas usually I have:
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<entry>
<author>
<name>Me =)</name>
</author>
<content>
<somefield1>
<Subfield>subfield data</subfield>
</somefield>
</content>
</entry>
</feed>
and can navigate using foreach entry as entry, selectsinglenode(/content/somefield1/subfield), innertext to get the data from the subfield for each entry, the new XML looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<atom:feed xmlns:atom="http://www.w3.org/2005/Atom">
<atom:entry>
<atom:author>
<name>Me =)</name>
</atom:author>
<atom:content>
<somefield1>
<Subfield>subfield data</subfield>
</somefield>
</atom:content>
</atom:entry>
</atom:feed>
selectsinglenode(/atom:content/somefield1/subfield) is definitely not going to work...any suggestions?
atom: is just the namespace, and possibly you might just ignore it. If it still not works, you may have to use:
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("atom", "http://www.w3.org/2005/Atom");
selectsinglenode("atom:content/somefield1/subfield", nsmgr);
Which is documented here

SOAPpy, C# and object passing

I'm trying to write a SOAPpy client to my C# WebService. It is arriving as null :(
How can I get any debug from the C# SOAP parser that WebService uses?
This is what Python sends:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/1999/XMLSchema"
>
<SOAP-ENV:Body>
<ns1:UpdateSession xmlns:ns1="http://www.xlogic.pl/SENACA" SOAP-ENC:root="1">
<xsd:Session>
<ID xsi:type="xsd:int">420</ID>
<RecordCreationTime SOAP-ENC:arrayType="xsd:ur-type[6]" xsi:type="SOAP-ENC:Array">
<item xsi:type="xsd:int">2010</item>
<item xsi:type="xsd:int">8</item>
<item xsi:type="xsd:int">17</item>
<item xsi:type="xsd:int">11</item>
<item xsi:type="xsd:int">13</item>
<item xsi:type="xsd:double">21.0</item>
</RecordCreationTime>
<ASP_SessionID xsi:type="xsd:string">92072674A04CB88D62776EA7</ASP_SessionID>
<LangID xsi:type="xsd:string">fr-FR</LangID>
<OneTimeKey xsi:type="xsd:string">a334cea18e014f4d8d04</OneTimeKey>
</xsd:Session>
</ns1:UpdateSession>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
This is what C# expects
<?xml version="1.0" encoding="utf-16"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://www.xlogic.pl/SENACA"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<tns:UpdateSession>
<s href="#id1"/>
</tns:UpdateSession>
<tns:Session id="id1" xsi:type="tns:Session">
<ID xsi:type="xsd:int">int</ID>
<RecordCreationTime
xsi:type="xsd:dateTime">dateTime</RecordCreationTime>
<ASP_SessionID xsi:type="xsd:string">string</ASP_SessionID>
<LangID xsi:type="xsd:string">string</LangID>
<OneTimeKey xsi:type="xsd:string">string</OneTimeKey>
</tns:Session>
</soap:Body>
</soap:Envelope>
Not a Python answer, but soapUI is a very useful facility for debugging and automated testing of web services. I used it heavily on a C# WCF project, with a variety of clients, including Python, Boo, Java, and C#.

Categories

Resources