XML string to XML document - c#

I have a whole XML document in a String which i need to convert to a XML document and parse tags in the document

This code sample is taken from csharp-examples.net, written by Jan Slama:
To find nodes in an XML file you can use XPath expressions. Method XmlNode.Selec­tNodes returns a list of nodes selected by the XPath string. Method XmlNode.Selec­tSingleNode finds the first node that matches the XPath string.
XML:
<Names>
<Name>
<FirstName>John</FirstName>
<LastName>Smith</LastName>
</Name>
<Name>
<FirstName>James</FirstName>
<LastName>White</LastName>
</Name>
</Names>
CODE:
XmlDocument xml = new XmlDocument();
xml.LoadXml(myXmlString); // suppose that myXmlString contains "<Names>...</Names>"
XmlNodeList xnList = xml.SelectNodes("/Names/Name");
foreach (XmlNode xn in xnList)
{
string firstName = xn["FirstName"].InnerText;
string lastName = xn["LastName"].InnerText;
Console.WriteLine("Name: {0} {1}", firstName, lastName);
}

Using Linq to xml
Add a reference to System.Xml.Linq
and use
XDocument.Parse(string xmlString)
Edit: Sample follows, xml data (TestConfig.xml)..
<?xml version="1.0"?>
<Tests>
<Test TestId="0001" TestType="CMD">
<Name>Convert number to string</Name>
<CommandLine>Examp1.EXE</CommandLine>
<Input>1</Input>
<Output>One</Output>
</Test>
<Test TestId="0002" TestType="CMD">
<Name>Find succeeding characters</Name>
<CommandLine>Examp2.EXE</CommandLine>
<Input>abc</Input>
<Output>def</Output>
</Test>
<Test TestId="0003" TestType="GUI">
<Name>Convert multiple numbers to strings</Name>
<CommandLine>Examp2.EXE /Verbose</CommandLine>
<Input>123</Input>
<Output>One Two Three</Output>
</Test>
<Test TestId="0004" TestType="GUI">
<Name>Find correlated key</Name>
<CommandLine>Examp3.EXE</CommandLine>
<Input>a1</Input>
<Output>b1</Output>
</Test>
<Test TestId="0005" TestType="GUI">
<Name>Count characters</Name>
<CommandLine>FinalExamp.EXE</CommandLine>
<Input>This is a test</Input>
<Output>14</Output>
</Test>
<Test TestId="0006" TestType="GUI">
<Name>Another Test</Name>
<CommandLine>Examp2.EXE</CommandLine>
<Input>Test Input</Input>
<Output>10</Output>
</Test>
</Tests>
C# usage...
XElement root = XElement.Load("TestConfig.xml");
IEnumerable<XElement> tests =
from el in root.Elements("Test")
where (string)el.Element("CommandLine") == "Examp2.EXE"
select el;
foreach (XElement el in tests)
Console.WriteLine((string)el.Attribute("TestId"));
This code produces the following output:
0002
0006

Depending on what document type you want you can use XmlDocument.LoadXml or XDocument.Load.

Try this code:
var myXmlDocument = new XmlDocument();
myXmlDocument.LoadXml(theString);

Related

remove root node but keep all child nodes

I have this xml that is parsed through
<ns0:Root xmlns:ns0="http://Core.Schemas.SouCurrencyRate">
<Test>
<CurrencyCode>SEKAUDPMI</CurrencyCode>
<CurrencyType>AUD</CurrencyType>
<CurrencyDate>2019 Juni</CurrencyDate>
<CurrencyRate>6.5656</CurrencyRate>
<RecordCreated>2019-06-30</RecordCreated>
<RecordCreatedSOP>2019-06-01</RecordCreatedSOP>
</Test>
<Test>
<CurrencyCode>SEKBRLPMI</CurrencyCode>
<CurrencyType>BRL</CurrencyType>
<CurrencyDate>2019 Juni</CurrencyDate>
<CurrencyRate>2.4376</CurrencyRate>
<RecordCreated>2019-06-30</RecordCreated>
<RecordCreatedSOP>2019-06-01</RecordCreatedSOP>
</Test>
<Test>
<CurrencyCode>SEKCADPMI</CurrencyCode>
<CurrencyType>CAD</CurrencyType>
<CurrencyDate>2019 Juni</CurrencyDate>
<CurrencyRate>7.0771</CurrencyRate>
<RecordCreated>2019-06-30</RecordCreated>
<RecordCreatedSOP>2019-06-01</RecordCreatedSOP>
</Test>
<Test>
<CurrencyCode>SEKCHFPMI</CurrencyCode>
<CurrencyType>CHF</CurrencyType>
<CurrencyDate>2019 Juni</CurrencyDate>
<CurrencyRate>951.7346</CurrencyRate>
<RecordCreated>2019-06-30</RecordCreated>
<RecordCreatedSOP>2019-06-01</RecordCreatedSOP>
</Test>
</ns0:Root>
The xml has ("Test") child nodes that occure a lot of time.
What I need to do is actually remove (" <ns0:Root xmlns:ns0="http://Core.Schemas.SouCurrencyRate"> ")
So that the XML output is
<Test>
<CurrencyCode>SEKAUDPMI</CurrencyCode>
<CurrencyType>AUD</CurrencyType>
<CurrencyDate>2019 Juni</CurrencyDate>
<CurrencyRate>6.5656</CurrencyRate>
<RecordCreated>2019-06-30</RecordCreated>
<RecordCreatedSOP>2019-06-01</RecordCreatedSOP>
</Test>
<Test>
<CurrencyCode>SEKBRLPMI</CurrencyCode>
<CurrencyType>BRL</CurrencyType>
<CurrencyDate>2019 Juni</CurrencyDate>
<CurrencyRate>2.4376</CurrencyRate>
<RecordCreated>2019-06-30</RecordCreated>
<RecordCreatedSOP>2019-06-01</RecordCreatedSOP>
</Test>
What I've tried to do is
System.Xml.XmlDocument xDoc = new System.Xml.XmlDocument();
xDoc.Load(bizobj.Message.BodyPart.GetOriginalDataStream());
System.Xml.XmlNode xNode = xDoc.FirstChild;
System.Xml.XmlNode xParent = xNode.ParentNode;
System.Xml.XmlNodeList xChilds = xNode.ChildNodes;
xDoc.RemoveChild(xNode);
foreach (System.Xml.XmlNode node in xChilds)
{
xParent.AppendChild(node);
}
But the main problem is that the returned xml only contains one child ("Test") and not the others.
I have also tried using Linq where I found this on a post
XDocument input = XDocument.Load("input.xml");
XElement firstChild = input.Root.Elements().First();
But this returns the same thing and does not help my case.
Can someone help me in the right direction?
Thanks.
If you really only need the text string, the fastest way to achieve this is using an XmlReader on the Root XElement:
XDocument xDoc = XDocument.Parse(bizobj.Message.BodyPart.GetOriginalDataStream());
XElement root = xDoc.Root;
XmlReader reader = root.CreateReader();
reader.MoveToContent();
string txt = reader.ReadInnerXml();
Just putting my final code here if anyone wants to take a look and use it.
Filburt was the one that threw me in the right direction anyway so look as his aswell.
System.Xml.XmlDocument xDoc = new System.Xml.XmlDocument();
xDoc.Load(bizobj.Message.BodyPart.GetOriginalDataStream());
string output = xDoc.DocumentElement.InnerXml;
byte[] byteArray = Encoding.ASCII.GetBytes(output);
MemoryStream stream = new MemoryStream(byteArray);
stream.Position = 0;
bizobj.Message.BodyPart.Data = stream;
return bizobj;

xml error:System.Xml.XPath.XPathException: Expression must evaluate to a node-set

I am trying to find a node in my xml file but getting the error ( see title)?
// instantiate XmlDocument and load XML from file
XmlDocument doc = new XmlDocument();
doc.Load(#"C:\temp\test2.xml");
var node = doc.SelectSingleNode("/Offers/Offer/ID=[text()='1']");
var test = node;
xml
<?xml version="1.0" encoding="utf-8"?>
<Offers>
<Offer>
<Model>AAAA</Model>
<ID>1</ID>
<Name>First offer</Name>
</Offer>
<Offer>
<Model>BBBB</Model>
<ID>2</ID>
<Name>Second offer</Name>
</Offer>
</Offers>
Remove the = after ID:
var node = doc.SelectSingleNode("/Offers/Offer/ID=[text()='1']");
becomes:
var node = doc.SelectSingleNode("/Offers/Offer/ID[text()='1']");

How do i use C# to to return element values using XPath?

I have a snippet of an xml file that looks like this:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="wa_xml2html.xsl"?>
<computeraudit>
<title>Computer Audit :: 11/13/2012 10:43:22 AM</title>
<category title="Loaded Modules">
<subcategory title="">
<recordset title="">
<fieldname>Name</fieldname>
<fieldname>Version</fieldname>
<fieldname>Modified</fieldname>
<fieldname>Manufacturer</fieldname>
<datarow>
<fieldvalue>XmlLite.dll</fieldvalue>
<fieldvalue>1.3.1000.0</fieldvalue>
<fieldvalue>7/13/2009 8:16:21 PM</fieldvalue>
<fieldvalue>Microsoft Corporation</fieldvalue>
</datarow>
<datarow>
<fieldvalue>zip.dll</fieldvalue>
<fieldvalue>6.0.250.6</fieldvalue>
<fieldvalue>5/25/2011 8:30:12 AM</fieldvalue>
<fieldvalue>Sun Microsystems, Inc.</fieldvalue>
</datarow>
</recordset>
</subcategory>
</category>
</computeraudit>
I'm trying to parse it with C# XPath and get each of the fieldvalue element values.
The c# code looks like this:
XPathNavigator nav;
XPathDocument docNav;
XPathNodeIterator NodeIter;
String strExpression;
docNav = new XPathDocument(#"C:\TEMP\WinAudit\test.xml");
nav = docNav.CreateNavigator();
strExpression = "/computeraudit/category[#title=\"Loaded Modules\"]/subcategory/recordset/datarow";
NodeIter = nav.Select(strExpression);
while (NodeIter.MoveNext())
{
Console.WriteLine(NodeIter.Current.Value);
}
Console.ReadLine();
It returns one line for each datarow node with all of the fieldvalue element values concatenated together.
How do I return each of the distinct values for each fieldvalue element?
Change your XPath expression to:
"/computeraudit/category[#title=\"Loaded Modules\"]/subcategory/recordset/datarow/fieldvalue"
Your selector is only selecting the datarow elements.
Try strExpression = "/computeraudit/category[#title=\"Loaded Modules\"]/subcategory/recordset/datarow/fieldvalue";

Little help with XLinq

I have this XML:
<Test>
<element>toto</element>
<element>tata</element>
</Test>
How I can get the nodes "element"?. I see on the web I can get them with:
var elements = from element in xmlDoc.Descendants("element")
select element;
But "elements" is empty!
EDIT 1: I'm loading the XDocument with this exact XML:
<Test xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">
<element>toto</element>
<element>tata</element>
</Test>
Ok well there's your problem, your names have to be qualified with the appropriate XML namespace.
XNamespace ns = "http://schemas.microsoft.com/ado/2007/08/dataservices";
var elements = xmlDoc.Descendants(ns + "element");
It is probably a problem with how you are creating your XDocument object. The following code works fine for me:
var doc = XDocument.Parse(#"
<Test>
<element>toto</element>
<element>tata</element>
</Test>");
var elements = doc.Descendants("element");
//prints "2"
Console.WriteLine(elements.Count());

Why doesn't this XPath query returns any nodes?

I'm querying Sharepoint server-side and getting back results as Xml. I want to slim down the Xml into something more lightweight before sending it to jQuery through a WebMethod.
However my XPath query isn't working. I thought the following code would return all Document nodes, but it returns nothing. I've used XPath a little before, I thought //Document do the trick.
C# XPath query
XmlDocument xmlResults = new XmlDocument();
xmlResults.LoadXml(xml); // XML is a string containing the XML source shown below
XmlNodeList results = xmlResults.SelectNodes("//Document");
XML being queried
<ResponsePacket xmlns="urn:Microsoft.Search.Response">
<Response domain="QDomain">
<Range>
<StartAt>1</StartAt>
<Count>2</Count>
<TotalAvailable>2</TotalAvailable>
<Results>
<Document relevance="126" xmlns="urn:Microsoft.Search.Response.Document">
<Title>Example 1.doc</Title>
<Action>
<LinkUrl size="32256" fileExt="doc">http://hqiis99/Mercury/Mercury documents/Example 1.doc</LinkUrl>
</Action>
<Description />
<Date>2010-08-19T14:44:56+01:00</Date>
</Document>
<Document relevance="31" xmlns="urn:Microsoft.Search.Response.Document">
<Title>Mercury documents</Title>
<Action>
<LinkUrl size="0" fileExt="aspx">http://hqiis99/mercury/Mercury documents/Forms/AllItems.aspx</LinkUrl>
</Action>
<Description />
<Date>2010-08-19T14:49:39+01:00</Date>
</Document>
</Results>
</Range>
<Status>SUCCESS</Status>
</Response>
</ResponsePacket>
You're trying to select Document elements which don't have a namespace... whereas the default namespace is actually "urn:Microsoft.Search.Response" here.
I think you want something like this:
XmlDocument xmlResults = new XmlDocument();
xmlResults.LoadXml(xml);
XmlNamespaceManager manager = new XmlNamespaceManager(xmlResults.NameTable);
manager.AddNamespace("ns", "urn:Microsoft.Search.Response.Document");
XmlNodeList results = xmlResults.SelectNodes("//ns:Document", manager);
This finds two elements.
If you can use LINQ to XML instead, it makes it all somewhat easier:
XDocument results = XDocument.Parse(xml);
XNamespace ns = "urn:Microsoft.Search.Response.Document";
var documents = results.Descendants(ns + "Document");
I love LINQ to XML's namespace handling :)
Alternatively, you could try the following and ignore the namespaces:
XmlDocument xmlResults = new XmlDocument();
xmlResults.LoadXml(xmlString);
XmlNodeList results = xmlResults.SelectNodes("//*[local-name()='Document']");

Categories