Reading the XMl Response and Extracting the nodes using c# - c#

I am trying to extract the XML Response from an API. My XML response looks like below. I tried different methods. can you please help me in reading and extracting the individual nodes from the XMl response.
For Example: I want to extract node from below XML response.
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">
<RichDBDS><TrxDetailCard><TRX_HD_Key>5437845</TRX_HD_Key> <Invoice_ID>189809</Invoice_ID><Date_DT>3/24/2016 1:34:44 PM</Date_DT><Merchant_Key>2202</Merchant_Key><Reseller_Key>2</Reseller_Key><TUser_Name_VC>ITSTEST.ISMI</TUser_Name_VC><Processor_ID>CC Processor</Processor_ID><TRX_Settle_Key></TRX_Settle_Key><Tip_Amt_MN></Tip_Amt_MN><Approval_Code_CH>24032016013444</Approval_Code_CH><Auth_Amt_MN>184.99</Auth_Amt_MN><IP_VC>66.55.53.68</IP_VC><Account_Type_CH>MANUAL</Account_Type_CH><Last_Update_DT></Last_Update_DT><Orig_TRX_HD_Key></Orig_TRX_HD_Key><Settle_Date_DT></Settle_Date_DT><Settle_Flag_CH>FALSE</Settle_Flag_CH><Trans_Type_ID>Sale</Trans_Type_ID><Void_Flag_CH>FALSE</Void_Flag_CH><CustomerID></CustomerID><AVS_Resp_CH>Y</AVS_Resp_CH><CV_Resp_CH>M</CV_Resp_CH><Host_Ref_Num_CH>0b144718-3597-4cfb-a2b5-058679510f29</Host_Ref_Num_CH><Zip_CH>30328</Zip_CH><Acct_Num_CH>1111</Acct_Num_CH><Total_Amt_MN>184.99</Total_Amt_MN><Exp_CH>0917</Exp_CH><Name_on_Card_VC>Kenneth Boler</Name_on_Card_VC><Type_CH>VISA</Type_CH><Cash_Back_Amt_MN></Cash_Back_Amt_MN><Result_CH>0</Result_CH><Result_Txt_VC>approval</Result_Txt_VC><Trans_Status>Settled</Trans_Status><PO_Num></PO_Num></TrxDetailCard></RichDBDS>

Try code like below using XML Linq. I used Load(FILENAME or URL) method, but you can also use Parse(STRING).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var results = doc.Descendants().Where(x => x.Name.LocalName == "TrxDetailCard").Select(y => new {
TRX_HD_Key = (int)y.Element(y.Name.Namespace + "TRX_HD_Key"),
Invoice_ID = (int)y.Element(y.Name.Namespace + "Invoice_ID"),
Date_DT = (DateTime)y.Element(y.Name.Namespace + "Date_DT"),
Merchant_Key = (int)y.Element(y.Name.Namespace + "Merchant_Key")
}).ToList();
}
}
}

Related

Update a specific node in XML using XmlDocument

I am new to managing XML, I've read a couple of articles but I'm confused when it comes to a specific XML that I am working on. Can someone help me with the right statement? I just want to update the value of the ListStart, but I am getting an error when compiling. I am updating that part by this:
XmlDocument soapEnvelopeDocument = new XmlDocument();
soapEnvelopeDocument.Load(#"path");
XmlNode myNode = soapEnvelopeDocument.SelectSingleNode("descendant::cet:GetListCustomElement[cet:GetListCustom/cet:ListID='101']");
soapEnvelopeDocument.LastChild.InnerText = sDate;
<soapenv:Header/>
<soapenv:Body>
<cet:GetListCustomElement>
<!--Zero or more repetitions:-->
<cet:GetListCustom>
<cet:ListID>101</cet:ListID>
<cet:ListStart>13.11.2020</cet:ListStart>
</cet:GetListCustom>
</cet:GetListCustomElement>
</soapenv:Body>
</soapenv:Envelope>```
You only supplied a piece of the xml without the namespaces. With Xml linq you can get the element without the namespaces. See code below :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement ListStart = doc.Descendants().Where(x => x.Name.LocalName == "ListStart").FirstOrDefault();
ListStart.SetValue("14.11.2020");
}
}
}

How do I update an Old element with a new one in C#/XML

Basically what I want to do is: Download a new XML file and replace some elements with the old one, For example replace this code:
<Run x:Name="Degree" Text="15"/>
with current degree, which is
<temperature value="280.15" min="278.15" max="281.15" unit="kelvin"/>
but I don't know how to do that. Here's my code I'm stuck with:
using (WebClient web = new WebClient())
{
string url = string.Format("https://samples.openweathermap.org/data/2.5/weather?q=London&mode=xml&appid=b6907d289e10d714a6e88b30761fae22");
var xml = web.DownloadString(url);
}
Use xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string URL = "https://samples.openweathermap.org/data/2.5/weather?q=London&mode=xml&appid=b6907d289e10d714a6e88b30761fae22";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(URL);
XElement temperature = doc.Descendants("temperature").FirstOrDefault();
temperature.SetAttributeValue("value", 281);
string oldXml = "<Root xmlns:x=\"abc\"><Run x:Name=\"Degree\" Text=\"15\"/></Root>";
XDocument oldDoc = XDocument.Parse(oldXml);
XElement run = oldDoc.Descendants("Run").FirstOrDefault();
run.ReplaceWith(temperature);
}
}
}

C# Read xml file that uses name prefixes but does not define namespace in the document itself

I have an xml file from a client. It uses name prefixes with many nodes. But it does not defines any namespace in the document. A sample is given below:
<?xml version="1.0"?>
<SemiconductorTestDataNotification>
<ssdh:DocumentHeader>
<ssdh:DocumentInformation>
<ssdh:Creation>2019-03-16T13:49:23</ssdh:Creation>
</ssdh:DocumentInformation>
</ssdh:DocumentHeader>
<LotReport>
<BALocation>
<dm:ProprietaryLabel>ABCDEF</dm:ProprietaryLabel>
</BALocation>
</LotReport>
</SemiconductorTestDataNotification>
I used following xml classes to read it but failed
System.Xml.Linq.XElement
System.Xml.XmlDocument
System.Xml.XmlReader
System.Xml.Linq.XDocument
It gives error:
'ssdh' is an undeclared prefix.
I know the prefixes namespaces. These would be:
xmlns:ssdh="urn:rosettanet:specification:system:StandardDocumentHeader:xsd:schema:01.13"
xmlns:dm="urn:rosettanet:specification:domain:Manufacturing:xsd:schema:01.14"
Adding these namespaces in the xml file by myself is not feasible because there would be many xml files and these files would come on daily basis.
Is it possible that I create a file (e.g. xsd) and write namespaces in them and read xml file using this (so called) schema file in C# code.
You need to use a non xml method for reading bad xml file. Try following code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication3
{
class Program1
{
const string BAD_FILENAME = #"c:\temp\test.xml";
const string Fixed_FILENAME = #"c:\temp\test1.xml";
static void Main(string[] args)
{
StreamReader reader = new StreamReader(BAD_FILENAME);
StreamWriter writer = new StreamWriter(Fixed_FILENAME);
string line = "";
while ((line = reader.ReadLine()) != null)
{
if (line == "<SemiconductorTestDataNotification>")
{
line = line.Replace(">",
" xmlns:ssdh=\"urn:rosettanet:specification:system:StandardDocumentHeader:xsd:schema:01.13\"" +
" xmlns:dm=\"urn:rosettanet:specification:domain:Manufacturing:xsd:schema:01.14\"" +
" >");
}
writer.WriteLine(line);
}
reader.Close();
writer.Flush();
writer.Close();
XDocument doc = XDocument.Load(Fixed_FILENAME);
}
}
}

Check if document received is XML or Edifact in custom pipeline component

Problem: I need to check whether an incoming document, inside an XML element, is XML or Edifact formatted. Depending on what format the document has, it needs to be processed accordingly.
Current solution: An XDocument instance is created from the incoming message. The incoming message is always XML.
var originalStream = pInMsg.BodyPart.GetOriginalDataStream();
XDocument xDoc;
using (XmlReader reader = XmlReader.Create(originalStream))
{
reader.MoveToContent();
xDoc = XDocument.Load(reader);
}
After this the document is extracted from the XML element "msgbody". Currently it assumes this to be XML formatted, which throws an error when the document is Edifact formatted. The code below extracts it, and the creates a new XDocument, which is sent to the MessageBox.
string extractedDocument = xDoc.Root.Element("msgbody").Value;
extractedDocument = HttpUtility.HtmlDecode(extractedDocument);
XDocument outputXml = XDocument.Parse(extractedDocument);
Example message from biztalk:
<NewTable>
<conversationID>2ff845e7-30a4-482e-98d6-8c3249c5dea1</conversationID>
<hostUTC>2018-12-17T12:17:04.107Z</hostUTC>
<msgType>INVOIC</msgType>
<msgid>721254</msgid>
<icref>36655</icref>
<msgFormat_org>EDIFACTBauhaus</msgFormat_org>
<msgFormat>EDI</msgFormat>
<msgbody>"Edifact or XML document"</msgbody>
<fromID>GLN:5790034516518</fromID>
<toID>GLN:5790000451485</toID>
</NewTable>
Question: How can I create a check for the document inside the msgbody tag, to determine whether it is XML or Edifact formatted, before processing it?
I like using a dictionary to get all the properties using xml linq. See code below. If you are getting string response the nuse instead of the Load(filename) method use Parse(string).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication93
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Dictionary<string, string> dict = doc.Descendants("NewTable").Elements()
.GroupBy(x => x.Name.LocalName, y => (string)y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}

Parse <a:FileContent> parameter in XML response

I have a web service that returns a response and I cant seem to find a good answer on how to parse the a:FileContent parameter using php or c#
The response looks like:
<GetReturnFileResponse xmlns="http://tempuri.org/">
<GetReturnFileResult xmlns:a="http://schemas.datacontract.org/2004/07/SigmaAPIService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:FileContent>/*Byte[] data type long string looks like 'IkRWTEoxMDI2LkVGQiIsIkVGVCIsIjgxOCIsIlZBTlNQRVlCUk9FQ0siLCIxMC8yNi8xNSIsIjA3Mzk3MjE4MSIsIjcwMDA3ODc5MDY5MDUwJSMDEiLCIxMC8yOC8xNSIsIlBCIiLCIiDQo=' here. **removed some chars just a sample*/</a:FileContent>
<a:Response>
<a:ResponseCode>1</a:ResponseCode>
<a:ResponseMessage>Successfully processed</a:ResponseMessage>
<a:ResponseType>Success</a:ResponseType>
</a:Response>
</GetReturnFileResult>
Easy with xml Linq
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\" ?>" +
"<GetReturnFileResponse xmlns=\"http://tempuri.org/\">" +
"<GetReturnFileResult xmlns:a=\"http://schemas.datacontract.org/2004/07/SigmaAPIService\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
"<a:FileContent>/*Byte[] data type long string looks like 'IkRWTEoxMDI2LkVGQiIsIkVGVCIsIjgxOCIsIlZBTlNQRVlCUk9FQ0siLCIxMC8yNi8xNSIsIjA3Mzk3MjE4MSIsIjcwMDA3ODc5MDY5MDUwJSMDEiLCIxMC8yOC8xNSIsIlBCIiLCIiDQo=' here. **removed some chars just a sample*/</a:FileContent>" +
"<a:Response>" +
"<a:ResponseCode>1</a:ResponseCode>" +
"<a:ResponseMessage>Successfully processed</a:ResponseMessage>" +
"<a:ResponseType>Success</a:ResponseType>" +
"</a:Response>" +
"</GetReturnFileResult>" +
"</GetReturnFileResponse>";
XDocument doc = XDocument.Parse(xml);
XElement fileContent = doc.Descendants().Where(x => x.Name.LocalName == "FileContent").FirstOrDefault();
XNamespace ns_a = fileContent.Name.Namespace;
}
}
}
​

Categories

Resources