Extract Xdocument soap response body into new Xdocument - c#

I have XML which is parsed into an XDocument:
<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>
<MyResponse xmlns="https://www.domain.net/">
<Node1>0</Node1>
</MyResponse>
</soap:Body>
</soap:Envelope>
Basically I am trying to create a new XDocument which has its root as
<MyResponse xmlns="https://www.domain.net/">
<Node1>0</Node1>
</MyResponse>
So in essence I am trying to extract this from the soap body. I have tried parsing this using Linq but cannot seem to return a new XDocument with this new root. Any ideas?
Thanks in advance

I think this will do the trick:
using System;
using System.Xml.Linq;
namespace SO39545160
{
class Program
{
static string xmlSource = "<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>" +
"<MyResponse xmlns = \"https://www.domain.net/\" >" +
"<Node1 > 0 </Node1 >" +
"</MyResponse>" +
"</soap:Body>" +
"</soap:Envelope>";
static void Main(string[] args)
{
XDocument xdoc = XDocument.Parse(xmlSource);
var subXml = xdoc.Document.Elements(XName.Get(#"{http://schemas.xmlsoap.org/soap/envelope/}Envelope")).Elements(XName.Get(#"{http://schemas.xmlsoap.org/soap/envelope/}Body")).Elements(XName.Get(#"{https://www.domain.net/}MyResponse"));
foreach (var node in subXml)
{
XDocument myRespDoc = new XDocument(node);
Console.WriteLine(myRespDoc);
}
Console.WriteLine();
Console.WriteLine("END");
Console.ReadLine();
}
}
}

Related

c# parse soap response when namespace prefix and xmlns prefix not equal

Hello I'm completely stuck, I could manage somehow get response from remote service.svc wsdl. Sorry for poor English.
there is my working sample, thanks to stackoverflow:
using System;
using System.Xml;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
string responseXml =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<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>" +
"<Company xmlns:b=\"http://www.someurl.com/Report/Company\">" +
"<b:LoginResult>" +
"<b:CookieName>FedAuth</b:CookieName>" +
"<b:ErrorCode>NoError</b:ErrorCode>" +
"<b:TimeoutSeconds>1800</b:TimeoutSeconds>" +
"<b:Parametrs>Zoroo 100</b:Parametrs>" +
"</b:LoginResult>" +
"</Company>" +
"</soap:Body>" +
"</Envelope>";
XmlDocument document = new XmlDocument();
document.LoadXml(responseXml); //loading soap message as string
XmlNamespaceManager manager = new XmlNamespaceManager(document.NameTable);
manager.AddNamespace("b", "http://www.someurl.com/Report/Company");
XmlNodeList xnList = document.SelectNodes("//b:LoginResult", manager);
int nodes = xnList.Count;
foreach (XmlNode xn in xnList)
{
string CookieName = xn["b:CookieName"].InnerText;
string ErrorCode = xn["b:ErrorCode"].InnerText;
string TimeoutSeconds = xn["b:TimeoutSeconds"].InnerText;
string Parametrs = xn["b:Parametrs"].InnerText;
Console.WriteLine();
Console.WriteLine(CookieName + ErrorCode + TimeoutSeconds + Parametrs);
Console.WriteLine();
}
}
}
}
My problem is that I cannot understand soap response message when I receive it like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<GCRResponse xmlns="http://www.someurl.com/Report">
<GCRResult xmlns:a="http://www.someurl.com/CReport" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:Company xmlns:b="http://www.someurl.com/Company">
<b:General>
<b:SomeInfo xmlns:c="http://www.someurl.com/Report/Common">
<c:Curr>BUM</c:Curr>
<c:LocalValue>1.00</c:LocalValue>
<c:Value>1.00</c:Value>
</b:SomeInfo>
<b:BS>Active</b:BS>
<b:CName>Zabis</b:CName>
<b:ES>NotSpecified</b:ES>
<b:NACELookup>
<a:NACE>NotSpecified</a:NACE>
</b:NACELookup>
<b:PC xmlns:c="http://www.someurl.com/Report/Common">
<c:Curr>BUM</c:Curr>
<c:LocalValue>1.00</c:LocalValue>
<c:Value>1.00</c:Value>
</b:PC>
</b:General>
</a:Company>
<a:CompanyRep i:nil="true" xmlns:b="http://www.someurl.com/Report/SomeReport"/>
<a:Parameters>
<a:Consent>true</a:Consent>
<a:IDNumber>30103331133</a:IDNumber>
<a:IDNumberType>RNumber</a:IDNumberType>
<a:InquiryReason>Application</a:InquiryReason>
<a:ReportDate>2017-09-26T08:57:26.6885118+03:00</a:ReportDate>
<a:Sections xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<b:string>SubjectInfo</b:string>
</a:Sections>
<a:SubjectType>Company</a:SubjectType>
</a:Parameters>
<a:ReportInfo xmlns:b="http://www.someurl.com/Report/ReportInfo">
<b:Created>2017-09-26T08:57:26.7197686+03:00</b:Created>
<b:ReferenceNumber>333368-9543457</b:ReferenceNumber>
<b:ReportStatus>ReportGenerated</b:ReportStatus>
<b:RequestedBy i:nil="true"/>
<b:Subscriber i:nil="true"/>
<b:Version>325</b:Version>
</a:ReportInfo>
</GCRResult>
</GCRResponse>
</s:Body>
</s:Envelope>
how to access to values if I have namespace with different prefix (a,b) than xmlns prefix for example here
<a:Company xmlns:b="http://www.someurl.com/Company">
and I cannot figure out how to work with manager.AddNamespace in this case when a:Company and is xmlns:b
How to access all values a,b,c?

Two identical namespaces with dirfferent prefixes in XDocument

So, I try creating Xml document with next code:
XNamespace spr1 = "urn:schemas-microsoft-com:office:spreadsheet";
XNamespace ex = "urn:schemas-microsoft-com:office:excel";
XNamespace spr2 = "urn:schemas-microsoft-com:office:spreadsheet";
XNamespace rec = "http://www.w3.org/TR/REC-html40";
var xworkbook = new XElement(spr1 + "Workbook");
xworkbook.Add(new XAttribute(XNamespace.Xmlns + "x", ex));
xworkbook.Add(new XAttribute(XNamespace.Xmlns +"ss", spr2));
xworkbook.Add(new XAttribute(XNamespace.Xmlns + "html", rec));
This code make next xml:
<ss:Workbook xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">
<!--Xml body-->
</ss:Workbook>
But I expect this:
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
</Workbook>
How to build Workbook element without "ss" prefix and with needed "xmlns" attribute?
LINQ to XML uses the namespace prefix that is closest as it looks through all the attributes in reverse order from the current element to the root. So if you add the default namespace explicitly at the end, then Workbook will use that and not the ss prefix.
XNamespace ss = "urn:schemas-microsoft-com:office:spreadsheet";
XNamespace ex = "urn:schemas-microsoft-com:office:excel";
XNamespace html = "http://www.w3.org/TR/REC-html40";
var workbook = new XElement(
ss + "Workbook",
new XAttribute(XNamespace.Xmlns + "x", ex),
new XAttribute(XNamespace.Xmlns + "ss", ss),
new XAttribute(XNamespace.Xmlns + "html", html),
new XAttribute("xmlns", ss)
);
This gives you the XML below:
<Workbook xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns="urn:schemas-microsoft-com:office:spreadsheet" />
As stated in the comments, the two documents in your question are semantically the same. Any XML parser shouldn't care about the difference between the two documents.
I usually do it like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string xml =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>" +
"<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"" +
" xmlns:x=\"urn:schemas-microsoft-com:office:excel\"" +
" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"" +
" xmlns:html=\"http://www.w3.org/TR/REC-html40\">" +
"</Workbook>";
XDocument doc = XDocument.Parse(xml);
XElement workbook = (XElement)doc.FirstNode;
XNamespace ssNs = workbook.GetNamespaceOfPrefix("ss");
XElement worksheet = new XElement(ssNs + "Worksheet");
workbook.Add(worksheet);
}
}
}

Transform XmlDocument into String with no Formatting for inclusion in SOAP Envelope

Is it possible to include a complete XmlDocument in a SOAP Envelope?
I have tried countless methods which caused a 500 Server Error when including the XML definition from the dataFile so have included a RemoveXmlDefinition to deal with that, now I am getting a 400 Bad Request Error.
No matter what I try, I end up with XML with formatting included in the final SOAP Envelope, I just need a string.
public string RemoveXmlDefinition(string xmlDocumentInnerXml)
{
var xDocument = XDocument.Parse(xmlDocumentInnerXml);
xDocument.Declaration = null;
var regex = new Regex(#">\s*<");
return regex.Replace(xDocument.ToString(), "><");
}
var dataFile = System.Web.HttpContext.Current.Server.MapPath("\\XML\\Test.xml");
var debug = "File Name = " + dataFile + "<br />";
var xmlDocument = new XmlDocument();
try
{
xmlDocument.XmlResolver = null;
xmlDocument.PreserveWhitespace = false;
xmlDocument.Load(dataFile);
}
catch (XmlException xmlException)
{
var test = xmlException.Message;
debug = debug + "Error Code = " + xmlException.GetHashCode() + "<br />";
debug = debug + "Error Reason = " + xmlException.InnerException + "<br />";
debug = debug + "Error Line = " + xmlException.LineNumber + "<br />";
}
var soapfile = Server.MapPath("/XML/Soap.xml");
if (System.IO.File.Exists(soapfile))
{
System.IO.File.Delete(soapfile);
}
var xmlTextWriter = new XmlTextWriter(dataFile, Encoding.UTF8) {Formatting = Formatting.None};
xmlDocument.Save(xmlTextWriter);
xmlTextWriter.Close();
string xmlDocumentInnerXml = RemoveXmlDefinition(xmlDocument.InnerXml);
using (var writer = new XmlTextWriter(soapfile, Encoding.UTF8) { Formatting = Formatting.Indented })
{
writer.WriteStartDocument();
writer.WriteStartElement("soap", "Envelope", "http://schemas.xmlsoap.org/soap/envelope/");
writer.WriteAttributeString("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
writer.WriteAttributeString("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
writer.WriteStartElement("soap", "Body", null);
writer.WriteStartElement("XmlString");
writer.WriteAttributeString("xmlns", "http://tempuri.org/");
writer.WriteFullElementString("xmlDocumentInnerXml", xmlDocumentInnerXml);
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
}
xmlDocumentInnerXml
<Affiliate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" leadnumber="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id=""><Details><Amount></Amount><Forename></Forename><Surname></Surname><Tel></Tel><Email></Email></Details></Affiliate>
soapEnvelope
<?xml version="1.0" encoding="utf-8" ?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<XmlString xmlns="http://tempuri.org/">
<xmlDocumentInnerXml>
<Affiliate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" leadnumber="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="">
<Details>
<Amount />
<Forename />
<Surname />
<Tel />
<Email />
</Details>
</Affiliate>
</xmlDocumentInnerXml>
</XmlString>
</soap:Body>
</soap:Envelope>
I have listed the sample SOAP 1.1 request XmlString is expecting below:
XmlString
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<XmlString xmlns="http://tempuri.org/">
<xmlDocumentInnerXml>string</xmlDocumentInnerXml>
</DmAppString>
</soap:Body>
</soap:Envelope>
Any assistance would be much appreciated.
I suspect that the reason for the errors is that you write the XML directly into the xmlDocumentInnerXml in the WriteFullElementString-method by using the WriteRaw-method:
public static void WriteFullElementString(this XmlTextWriter writer, string localName, string value)
{
writer.WriteStartElement(localName);
writer.WriteRaw(value);
writer.WriteFu‌​llEndElement();
}
This might lead to some schema validation errors. In order to include the XML string as a CData-block and thereby encode it correctly, you can use the WriteCData-method instead of WriteRaw:
public static void WriteFullElementString(this XmlTextWriter writer, string localName, string value)
{
writer.WriteStartElement(localName);
writer.WriteCData(value);
writer.WriteFu‌​llEndElement();
}

Check if element exists in XML using c#

Why do I get false value for hasIdentifier variable, when I see in i-th document anything_start_i.xml that there is <identifier>value</identifier> element.
XDocument doc = XDocument.Load(args[0] + "/?verb=GetRecord&metadataPrefix=p3dm&identifier=" + i);
doc.Save("anything_start" + i + ".xml");
bool hasIdentifier = doc.Elements("identifier").Any();
Console.WriteLine(hasIdentifier);
Tried with Descendants instead of Elements, and again false.
XML:
<?xml version="1.0" encoding="utf-8"?>
<OAI-PMH xmlns="..." xmlns:xsi="..." xsi:schemaLocation="...">
<responseDate>...</responseDate>
<request verb="GetRecord" identifier="1"</request>
<GetRecord>
<record>
<header>
<identifier>1</identifier>
<datestamp>...</datestamp>
</header>
<metadata>
<P3DM xmlns="..." xsi:schemaLocation="...">
<MODELINFOID>1</MODELINFOID>
<TITLE>Roth</TITLE>
....
Well, I would like to save all documents, and trying to stop saving when there is no documents any more (actually there is but without meaningful data). So, this is how i started:
static void Main(string[] args)
{
var i = 1;
bool work = true;
do{
XDocument doc = XDocument.Load(args[0] + "/?verb=GetRecord&metadataPrefix=p3dm&identifier=" + i);
bool hasIdentifier = doc.Elements("identifier").Any();
if (hasIdentifier) {
doc.Save("anything" + i + ".xml");
i++;
}else{
work = false;
}
} while (work);
XNamespace ns = "you namespace goes here";
bool hasIdentifier = doc.Descendants(ns + "identifier").Any();

How to get an XML value out of another XML value at C#

I need to get a value out of an XML file...
I have this XML file for example:
<?xml version="1.0"?>
<hwids>
<user>
<userName>Ivar</userName>
<hwid>BFEB-FBFF-0000-06FD-C87C-FA30</hwid>
</user>
<user>
<userName>Jerremy</userName>
<hwid>BFE9-FBFF-0000-06E8-E41E-5034</hwid>
</user>
</hwids>
Now, if I have the value BFEB-FBFF-0000-06FD-C87C-FA30, how do I get the name Ivar, out of the xml file trough C#?
I used in my application something like this:
using System.Data;
DataSet dataSet = new DataSet();
dataSet.ReadXml(xmlFullPath, XmlReadMode.Auto);
DataRow[] dataRows = dataSet.Tables["user"].Select("hwid like 'BFEB-FBFF-0000-06FD-C87C-FA30'");
if (dataRows.Length == 0)
return;
string sUser = dataRows[0]["userName"].ToString();
you can accomplish this also with XmlDocument of the System.Xml namespace, which is supported in .NET 3.0
var xml = "<?xml version=\"1.0\"?>" +
"<hwids> " + "<user>" +
"<userName>Ivar</userName>" +
"<hwid>BFEB-FBFF-0000-06FD-C87C-FA30</hwid>"+
"</user> " +
"<user>" +
"<userName>Jerremy</userName>" +
"<hwid>BFE9-FBFF-0000-06E8-E41E-5034</hwid>" +
"</user>" +
"</hwids>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
var ret = doc.GetElementsByTagName("userName");
for (int i = 0; i < ret.Count; i++)
{
Debug.WriteLine(ret.Item(i).InnerText);
}
I think this should work:
XElement root = XElement.Load("file.xml");
IEnumerable<XElement> hws =
from el in root.Elements("user")
where (string)el.Element("userName") == "Ivar"
select el.Descendant("hwid);
Haven't tested it out.

Categories

Resources