Retrieve a value from an XML - c#

Here is my xml file:
<?xml version="1.0" encoding="utf-8"?>
<PutUserLinkRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<request xmlns="http://tempuri.org">
<id S="ID-KMEHR" SV="1.0" SL="">Delta.PutUserLink.25/08/2017 13:07:43</id>
<author>
<hcparty>
</hcparty>
</author>
</request>
<userlink xmlns="http://tempuri.org">
<user1>
<cd S="CD-USERTYPE" SV="1.0" SL="" DN="" L="fr">patient</cd>
<patient>
<id S="ID-PATIENT" SV="1.0" SL="">97031038713</id>
</patient>
</user1>
<user2>
</user2>
<type S="CD-USERLINK" SV="1.0" SL="" DN="" L="fr">patientassent</type>
</userlink>
</PutUserLinkRequest>
I cannot retrieve the value 97031038713
XmlDocument _xmlDoc = new XmlDocument();
_xmlDoc.LoadXml(_mRec.Content);
XmlNamespaceManager manager = new XmlNamespaceManager(_xmlDoc.NameTable);
manager.AddNamespace("ns","http://tempuri.org");
Then I tried different things but without success
`<?xml version="1.0" encoding="utf-8"?>
<PutUserLinkRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<request xmlns="http://tempuri.org">
<id S="ID-KMEHR" SV="1.0" SL="">Delta.PutUserLink.25/08/2017 13:07:43</id>
<author>
<hcparty>
</hcparty>
</author>
</request>
<userlink xmlns="http://tempuri.org">
<user1>
<cd S="CD-USERTYPE" SV="1.0" SL="" DN="" L="fr">patient</cd>
<patient>
<id S="ID-PATIENT" SV="1.0" SL="">97031038713</id>
</patient>
</user1>
<user2>
</user2>
<type S="CD-USERLINK" SV="1.0" SL="" DN="" L="fr">patientassent</type>
</userlink>
</PutUserLinkRequest>

You can do this trivially with LINQ to XML:
var doc = XDocument.Parse(xml);
XNamespace ns = "http://tempuri.org";
var id = (string) doc.Descendants(ns + "patient")
.Elements(ns + "id")
.Single();
See this fiddle for a demo.

Related

Using C# to copy different nodes from two files and pasting it on a third one

I have a task that is very cumbersome, as I have to do it by hand (my company bought a tool for a ludicrous amount of money that doesn't work anymore).
I have two XML lists, each of them has half of it missing, so I need to piece it together into a third one before sending it to the system. As well as changing the header to the date I'm sending the file.
I've managed to set up the input for the date, it's easy enough to ask the user for the input. But the rest of the task is driving me mad, I tried many things I've found around here and on the Microsoft forums, to no avail... this task is killing me because I'm the only one that is "tech savvy" to do it (it's literally monkey job of copying and pasting text from XMLs).
It's not trucks and cars, obviously, and there are more files than two, but they all are like this: one kind has only cars, with an empty truck node, and the other has trucks but with empty cars node.
Example of File 1
<?xml version="1.0" encoding="utf-8"?>
<document>
<header>
<startDate>01/01/2020</startDate>
<endDate>01/02/2020</endDate>
</header>
<body>
<cars>
<car>
<ID>1</ID>
<Name>Blue Car</Name>
</car>
<car>
<ID>2</ID>
<Name>Red Car</Name>
</car>
</cars>
<trucks>
</trucks>
</body>
</document>
Example of File 2
<?xml version="1.0" encoding="utf-8"?>
<document>
<header>
<startDate>01/01/2020</startDate>
<endDate>01/02/2020</endDate>
</header>
<body>
<cars>
</cars>
<trucks>
<truck>
<ID>1</ID>
<Name>Blue Truck</Name>
</truck>
<truck>
<ID>2</ID>
<Name>Red Truck</Name>
</truck>
</trucks>
</body>
</document>
Example of File 3
<?xml version="1.0" encoding="utf-8"?>
<document>
<header>
<Date>03/02/2020</Date>
</header>
<body>
<cars>
<car>
<ID>1</ID>
<Name>Blue Car</Name>
</car>
<car>
<ID>2</ID>
<Name>Red Car</Name>
</car>
</cars>
<trucks>
<truck>
<ID>1</ID>
<Name>Blue Truck</Name>
</truck>
<truck>
<ID>2</ID>
<Name>Red Truck</Name>
</truck>
</trucks>
</body>
</document>
Use XSLT:
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="*">
<xsl:copy><xsl:apply-templates/></xsl:copy>
</xsl:template>
<xsl:template match="cars">
<cars>
<xsl:copy-of select="car"/>
<xsl:copy-of select="document('other-doc.xml')//car"/>
</cars>
</xsl:template>
<xsl:template match="trucks">
<trucks>
<xsl:copy-of select="truck"/>
<xsl:copy-of select="document('other-doc.xml')//truck"/>
</trucks>
</xsl:template>
</xsl:transform>
This can of course be run very easily using from C# using the System.Xml.Xsl processor.
I haven't tried to do anything with the dates in the header because I'm not sure what your logic is, but that's easily added.
If you want to use a later version of XSLT it becomes a little shorter but then you need to install a third-party library:
<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="cars">
<cars>
<xsl:copy-of select="car, doc('other-doc.xml')//car"/>
</cars>
</xsl:template>
<xsl:template match="trucks">
<trucks>
<xsl:copy-of select="truck, doc('other-doc.xml')//truck"/>
</trucks>
</xsl:template>
</xsl:transform>
Please use below code
string xml1 = #"<document><header><startDate>01/01/2020</startDate><endDate> 01/02/ 2020</endDate></header><body><cars><car><ID>1</ID><Name>Blue Car</Name></car><car><ID>2</ID><Name>Red Car</Name></car></cars><trucks></trucks></body></document>";
//load xml in StringReader
StringReader sr = new StringReader(xml1);
DataSet ds1 = new DataSet();
// Read XML in ds1
ds1.ReadXml(sr);
string xml2 = #"<document><header><startDate> 01 / 01 / 2020 </startDate><endDate> 01 / 02 / 2020</endDate></header><body><cars></cars><trucks><truck><ID> 1 </ID><Name> Blue Truck </Name></truck><truck><ID>2</ID><Name>Red Truck</Name></truck></trucks></body></document>";
sr = new StringReader(xml2);
DataSet ds2 = new DataSet();
ds2.ReadXml(sr);
DataSet dsHeaders = new DataSet();
dsHeaders.Tables.Add(ds1.Tables[0].Copy());
string headersXML = dsHeaders.GetXml();
headersXML = headersXML.Replace("<NewDataSet>", "").Replace("</NewDataSet>", "");
// Console.WriteLine(headersXML.Trim());
DataSet dsCars = new DataSet("Cars");
dsCars.Tables.Add(ds1.Tables[3].Copy());
string carsXML = dsCars.GetXml();
// Console.WriteLine(carsXML);
DataSet dsTrucks = new DataSet("Trucks");
dsTrucks.Tables.Add(ds2.Tables[3].Copy());
string trucksXML = dsTrucks.GetXml();
// Console.WriteLine(trucksXML);
string resultXML = #"<document>" + headersXML + "<body>" + Environment.NewLine + carsXML + trucksXML + Environment.NewLine + "</body>" + Environment.NewLine + "</document>";
Console.WriteLine(resultXML);
Your required XML
<document>
<header>
<startDate>01/01/2020</startDate>
<endDate> 01/02/ 2020</endDate>
</header>
<body>
<Cars>
<car>
<ID>1</ID>
<Name>Blue Car</Name>
</car>
<car>
<ID>2</ID>
<Name>Red Car</Name>
</car>
</Cars><Trucks>
<truck>
<ID> 1 </ID>
<Name> Blue Truck </Name>
</truck>
<truck>
<ID>2</ID>
<Name>Red Truck</Name>
</truck>
</Trucks>
</body>
</document>
Using xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication2
{
class Program
{
const string FILE1 = #"c:\TEMP\TEST.XML";
const string FILE2 = #"c:\TEMP\TEST1.XML";
static void Main(string[] args)
{
string xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><document></document>";
XDocument doc3 = XDocument.Parse(xml);
XElement doc = doc3.Root;
doc.Add(new XElement("header", new XElement("Date", DateTime.Now.ToString("mm/dd/yyyy"))));
XDocument doc1 = XDocument.Load(FILE1);
XDocument doc2 = XDocument.Load(FILE2);
XElement body = new XElement("body");
doc.Add(body);
XElement cars = new XElement("cars");
body.Add(cars);
List<XElement> cars1 = doc1.Descendants("car").ToList();
cars.Add(cars1);
List<XElement> cars2 = doc2.Descendants("car").ToList();
cars.Add(cars2);
XElement trucks = new XElement("trucks");
body.Add(trucks);
List<XElement> trucks1 = doc1.Descendants("truck").ToList();
trucks.Add(trucks1);
List<XElement> trucks2 = doc2.Descendants("truck").ToList();
trucks.Add(trucks2);
}
}
}

Unable to parse xml string using Xdocument and Linq

I would like to parse the below xml using XDocument in Linq.
<?xml version="1.0" encoding="UTF-8"?>
<string xmlns="http://tempuri.org/">
<Sources>
<Item>
<Id>1</Id>
<Name>John</Name>
</Item>
<Item>
<Id>2</Id>
<Name>Max</Name>
</Item>
<Item>
<Id>3</Id>
<Name>Ricky</Name>
</Item>
</Sources>
</string>
My parsing code is :
var xDoc = XDocument.Parse(xmlString);
var xElements = xDoc.Element("Sources")?.Elements("Item");
if (xElements != null)
foreach (var source in xElements)
{
Console.Write(source);
}
xElements is always null. I tried using namespace as well, it did not work. How can I resolve this issue?
Try below code:
string stringXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><string xmlns=\"http://tempuri.org/\"><Sources><Item><Id>1</Id><Name>John</Name></Item><Item><Id>2</Id><Name>Max</Name></Item><Item><Id>3</Id><Name>Ricky</Name></Item></Sources></string>";
XDocument xDoc = XDocument.Parse(stringXml);
var items = xDoc.Descendants("{http://tempuri.org/}Sources")?.Descendants("{http://tempuri.org/}Item").ToList();
I tested it and it correctly shows that items has 3 lements :) Maybe you used namespaces differently (it's enough to inspect xDoc objct in object browser and see its namespace).
You need to concatenate the namespace and can directly use Descendants method to fetch all Item nodes like:
XNamespace ns ="http://tempuri.org/";
var xDoc = XDocument.Parse(xmlString);
var xElements = xDoc.Descendants(ns + "Item");
foreach (var source in xElements)
{
Console.Write(source);
}
This prints on Console:
<Item xmlns="http://tempuri.org/">
<Id>1</Id>
<Name>John</Name>
</Item><Item xmlns="http://tempuri.org/">
<Id>2</Id>
<Name>Max</Name>
</Item><Item xmlns="http://tempuri.org/">
<Id>3</Id>
<Name>Ricky</Name>
</Item>
See the working DEMO Fiddle

Parsing Soap Message

I recently started to work with SOAP.
Right now I am trying to parse SOAP message in C#.
Message is as it follows:
<SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<ns1:getBuildingsResponse xmlns:ns1="http://someserver.net/~username/lab/servis?ws=1">
<return SOAP-ENC:arrayType="ns2:Map[2]" xsi:type="SOAP-ENC:Array" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<item xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">id</key>
<value xsi:type="xsd:string">1</value>
</item>
<item>
<key xsi:type="xsd:string">code</key>
<value xsi:type="xsd:string">345-GESG</value>
</item>
<item>
<key xsi:type="xsd:string">name</key>
<value xsi:type="xsd:string">Building 1</value>
</item>
</item>
<item xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">id</key>
<value xsi:type="xsd:string">7590913</value>
</item>
<item>
<key xsi:type="xsd:string">code</key>
<value xsi:type="xsd:string">353-gr</value>
</item>
<item>
<key xsi:type="xsd:string">name</key>
<value xsi:type="xsd:string">Building 2</value>
</item>
</item>
</return>
I want to extract values of keys id,code and name.
I tried doing something like this:
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(client.Invoke("getBuildings").ToString());
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdoc.NameTable);
nsmgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
nsmgr.AddNamespace("i", "item");
XmlNodeList xNodelst = xdoc.DocumentElement.SelectNodes("item", nsmgr);
Console.WriteLine(xNodelst.Count);
foreach (XmlNode xn in xNodelst)
{
Console.WriteLine(xn.Value);
}
The problem is, I don't know how to act with tags that have no namespace...
This line of code:
Console.WriteLine(xNodelst.Count);
always prints 0, but I want it to print 2, since I have 2 elements in array (ns2:Map[2]).
Meaning, I want to loop through all of these elements:
<item xsi:type="ns2:Map">
Any help will be appreciated.
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(client.Invoke("getBuildings").ToString());
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdoc.NameTable);
XmlNodeList nodes = xDoc.SelectNodes("//item[#xsi:type='ns2:Map']",nsmgr);
var nodeCount=nodes.Count;
try this, this might help you.

Copy specified child node from one xml file to another xml file in C#

Below are my two xml files-
Sample xml file
<tbltemp>
<Details>
<Id>1</Id>
<Name>John</Name>
<Date>25.09.2016</Date>
<Time>09:30:45</Time>
<Flag>1</Flag>
</Details>
<Details>
<Id>2</Id>
<Name>John</Name>
<Date>25.09.2016</Date>
<Time>01:30:45</Time>
<Flag>1</Flag>
</Details>
<Details>
<Id>3</Id>
<Name>John</Name>
<Date>25.09.2016</Date>
<Time>11:36:45</Time>
<Flag>1</Flag>
</Details>
<Details>
<Id>1</Id>
<Name>Jack</Name>
<Date>25.09.2016</Date>
<Time>11:36:45</Time>
<Flag>1</Flag>
</Details>
</tbltemp>
DBfile.xml
<tbltemp>
<Data>
<Id>1</Id>
<Name>John</Name>
<Age>23</Age>
<Team>Software</Team>
<Flag>1</Flag>
</Data>
<Data>
<Id>2</Id>
<Name>John</Name>
<Age>23</Age>
<Team>Software</Team>
<Flag>1</Flag>
</Data>
<Data>
<Id>3</Id>
<Name>John</Name>
<Age>23</Age>
<Team>Software</Team>
<Flag>1</Flag>
</Data>
<Data>
<Id>1</Id>
<Name>Jack</Name>
<Age>24</Age>
<Team>Software</Team>
<Flag>1</Flag>
</Data>
</tbltemp>
I want to copy Date and time in DBfile.xml file from sample xml file where Ids match for both the xml file.
I want the DBfile.xml like this-
<tbltemp>
<Data>
<Id>1</Id>
<Name>John</Name>
<Age>23</Age>
<Team>Software</Team>
<Date>25.09.2016</Date>
<Time>09:30:45</Time>
<Flag>1</Flag>
</Data>
<Data>
<Id>2</Id>
<Name>John</Name>
<Age>23</Age>
<Team>Software</Team>
<Date>25.09.2016</Date>
<Time>01:30:45</Time>
<Flag>1</Flag>
</Data>
<Data>
<Id>3</Id>
<Name>John</Name>
<Age>23</Age>
<Team>Software</Team>
<Date>25.09.2016</Date>
<Time>11:36:45</Time>
<Flag>1</Flag>
</Data>
<Data>
<Id>1</Id>
<Name>Jack</Name>
<Age>24</Age>
<Team>Software</Team>
<Date>25.09.2016</Date>
<Time>11:36:45</Time>
<Flag>1</Flag>
</Data>
</tbltemp>
I have been using code like this
strDetails = "sample.xml";
strDBDir = "DBfile.xml";
var xDoc1 = XDocument.Load(strDetails);
var xDoc2 = XDocument.Load(strDBDir);
var doc1Entries = xDoc1.Descendants("Details");
/// var cloneEntries = doc1Entries.Select(x => new XElement(x));//"AgentId").Value == AgentId.ToString()
var cloneEntries = doc1Entries.Select(x => new XElement(x));
xDoc2.Descendants("Date").Last().AddFirst(cloneEntries);
xDoc2.Descendants("Time").Last().AddAfterSelf(cloneEntries);
xDoc2.Save(strDBDir);
But unable to copy data from one file to other.,Instead it is just adding loginid into DBfile.xml
Can anyone guide here please.
Using linq join
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)
{
XDocument sampleDoc = XDocument.Load(#"c:\temp\sample.xml");
XDocument dbDoc = XDocument.Load(#"c:\temp\dbfile.xml");
var merge =
(from db in dbDoc.Descendants("Data")
join sample in sampleDoc.Descendants("Details") on new { id = (int)db.Element("Id"), name = (string)db.Element("Name") } equals new { id = (int)sample.Element("Id"), name = (string)sample.Element("Name") }
select new { db = db, sample = sample });
foreach (var row in merge)
{
row.db.Add(new object[] {
row.sample.Element("Date"),
row.sample.Element("Time")
});
}
}
}
}

XMLDocument Access To Last Child

i'm developing sitemap project and have a problem;
this is my xml file
<?xml version="1.0" encoding="UTF-8"?>
<urlset>
<url ID="1">
<loc>http://www.serkancamur.com/Site/Index/sayfa/Hakkimda</loc>
<changefreq>Daily</changefreq>
<priority>0,9</priority>
</url>
</urlset>
this is my c# code:
int ID = Convert.ToInt32(doc.SelectSingleNode("urlset").LastChild.Attributes["ID"].Value);
this works but look to urlset element attributes:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" schemaLocation="http://www.serkancamur.com/sitemap.xsd">
<url ID="1">
<loc>http://www.serkancamur.com/Site/Index/sayfa/Hakkimda</loc>
<changefreq>Daily</changefreq>
<priority>0,9</priority>
</url>
</urlset>
i only added attributes to urlset element,so why this doesn't work?
You need to use XmlNamespaceManager
Try this
int id = 0;
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("x", "http://www.sitemaps.org/schemas/sitemap/0.9");
var urlset = doc.SelectSingleNode("//x:urlset", nsmgr);
id = Convert.ToInt32(urlset.LastChild.Attributes["ID"].Value);
Hope this helps

Categories

Resources