I have an xml file whose structure goes as under(partial)
<?xml version="1.0" encoding="UTF-8"?>
<TestRun id="ee3838c9-a7e2-4ddf-acb1-58589e39422d" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<TestSettings name="LocalSettings" id="e445106a-c672-4959-94d3-ec8cef9ac7e4">
<Results>
<UnitTestResult executionId="0e790a10-105f-44b1-a8f7-f72709651c17" testId="ae349466-4276-cfa9-908c-026a8589473b" testName="ValidateEmailAddressAndCompanyCode7" computerName="ACCUREVDEV" duration="00:00:41.4297842" startTime="2013-02-27T23:18:52.0238567-08:00" endTime="2013-02-27T23:19:34.0057439-08:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="0e790a10-105f-44b1-a8f7-f72709651c17">
</UnitTestResult>
<UnitTestResult executionId="e9e7679d-fc39-43b7-a096-819f054a3795" testId="1a808be5-21a5-37c4-5892-2969707ae42f" testName="AccountExtensionSubscriptionWithOneMachineAndThreeSubscriptionsTest_withExpiredMachines" computerName="ACCUREVDEV" duration="00:00:56.1243356" startTime="2013-02-27T23:19:34.0174655-08:00" endTime="2013-02-27T23:20:30.8418287-08:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="e9e7679d-fc39-43b7-a096-819f054a3795">
</UnitTestResult> .............................
...............................
As can be make out that, there is a namespace involved
xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010"
Now if I do
string source = #"D:\23_18_43.trx";
XDocument xDoc = XDocument.Load(source);
var xxxx = (from data in xDoc.Descendants("Results")
select data).Descendants("UnitTestResult").ToList();
There is no value coming.
Whereas , if I omit the namespace and do my processing, it works.
How can I proceed without removing the namespace explicitly from the source file? Can it be done programatically?
Thanks
To find a node in XML with a default namespace, you need to still search for that node using the namespace.
Eg.
XNamespace defaultNs = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010";
and then in your "query";
var xxxx = (from data in xDoc.Descendants(defaultNs + "Results")
select data).Descendants(defaultNs +"UnitTestResult").ToList();
Related
How can I read the content of the childnotes using Xpath?
I have already tried this:
var xml = new XmlDocument();
xml.Load("server-status.xml");
var ns = new XmlNamespaceManager(xml.NameTable);
ns.AddNamespace("ns", "namespace");
var node = xml.SelectSingleNode("descendant::ns:server[ns:ip-address]", ns)
Console.WriteLine(node.InnerXml)
But I only get a string like this:
<ip-address>127.0.0.50</ip-address><name>Server 1</name><group>DATA</group>
How can I get the values individually?
Xml file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<server-status xmlns="namespace">
<server>
<ip-address>127.0.0.50</ip-address>
<name>Server 1</name>
<group>DATA</group>
</server>
</server-status>
You're using XML namespaces in XPath correctly.
However, your original XPath,
descendant::ns:server[ns:ip-address]
says to select all ns:server elements with ns:ip-address children.
If you wish to select the ns:ip-address children themselves, instead use
descendant::ns:server/ns:ip-address
Similarly, you could select ns:name or ns:group elements.
While parsing xml by linq to xml, I came across a strange behaviour (atleast to me). Below is the first xml I parsed
`<?xml version="1.0" encoding="UTF-8"?>
<TestRun>
<UnitTestResult testName = "Arun" outcome = "i">
</UnitTestResult>
<UnitTestResult testName = "Arun1" outcome = "i">
</UnitTestResult>
</TestRun>`
My Code looks like
XDocument doc = XDocument.Parse(fileContents);
var result = doc.Descendants("UnitTestResult");
The above works fine. But If my root node contain attributes the same code is not working. What could be the reason. XML sample below
<?xml version="1.0" encoding="UTF-8"?>
<TestRun id="7903b4ff-8706-4379-b9e8-567034b70abb" name="inaambika#INBELW013312A 2016-02-26 16:55:14" runUser="STC\inaambika" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<UnitTestResult testName = "Arun" outcome = "i">
</UnitTestResult>
<UnitTestResult testName = "Arun1" outcome = "i">
</UnitTestResult>
</TestRun>
XDocument doc = XDocument.Parse(fileContents);
var result = doc.Descendants("UnitTestResult");
This one below is not ordinary attribute, it is default namespace declaration :
xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010"
Having default namespace declared at the root element level, the root element and all descendant elements without prefix (in this case it means all elements in the posted XML) are in that namespace.
You can use XNamespace + element-local-name to reference element in namespace :
XDocument doc = XDocument.Parse(fileContents);
XNamespace d = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010"
var result = doc.Descendants(d+"UnitTestResult");
<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Element xsi:Attribute="Test"></Element>
</Root>
I'm trying to read the "xsi:Attribute" attribute; the code is like this:
var doc = XDocument.Load(new StringReader(xmlText));
var node = doc.Root.Descendants().First();
XNamespace myNamespace = "xsi";
var attribute = node.Attributes(myNamespace + "Attribute").First();
It throws a "Sequence contains no elements" exception in the last line. What am I doing wrong?
You need to use the actual namespace, not "xsi", which is just a local lookup within the XML file itself for the real namespace:
XNamespace myNamespace = "http://www.w3.org/2001/XMLSchema-instance";
Try this (I believe its more generic):
XNamespace myNamespace = doc.Root.GetNamespaceOfPrefix("xsi");
I have the following XML file which has the namespace as shown...
I have to change the inner text of XML file but need suggestion how to do it.
My XML file is:
<?xml version="1.0"?>
<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">
<buttons>
<workshop1>Google</workshop1>
<workshop1>Yahoo</workshop1>
<url1>www.google.co.uk</url1>
</buttons>
</Report>
I have to change the inner text of second node workshop1 from "Yahoo" to "new".
Do this using XElement.
The "problem" you probably had is due to the namespace this xml has:
XElement xml = getXml(); // get your xml from a service\file\ftp etc..
XNamespace ns = "http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition";
xml.Descendants(ns + "workshop1").First().Value = "new";
Your output:
<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">
<buttons>
<workshop1>new</workshop1>
<url1>www.google.co.uk</url1>
</buttons>
</Report>
For more than one node use this:
XNamespace ns = "http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition";
var nodes = xml.Descendants(ns + "workshop1").ToList();
nodes[0].Value = "new";
nodes[1].Value = "new2";
// etc....
Friends,
My school project is having an xml data file:
<patients>
<patient>
<regNo>2012/Mar/003</regNo>
<name>Jhon</name>
<add>Somewhere</add>
<mobile>0000</mobile>
.
.
.
<stay>2</stay>
<costofroom>100</costofroom>
<total>200</total>
</patient>
</patients>
My Windowsform "EditPatients_Load" is able to fetch all info of patient Jhon, and now let's assume that the Admin needs to change some information in the form & resubmit.
Then how to write back all values to Jhon's account in the same xml
file????
I'm not able to makeup the logical code, even if I check the node if (patients.paptient.name = "nameComboBox.text").... how to make sure that I'm writing other values on proper place?
Rgrdz,
Try this:
//string xml =
//#"<patients><patient><regNo>2012/Mar/003</regNo><name>Jhon</name><add>Somewhere
//</add><mobile>0000</mobile><stay>2</stay><costofroom>100</costofroom><total>200</total>
//</patient></patients>";
XDocument xmlDoc = XDocument.Load(#"c:\abc.xml");
var items = (from item in xmlDoc.Descendants("patient")
where item.Element("name").Value == "Jhon"
select item);
if (items.Count() > 0)
{
var item = items.First();
item.SetElementValue("add", "New New Address");
xmlDoc.Save(#"c:\abc.xml", SaveOptions.None);
}
You can get single element using
var item = (from item in xmlDoc.Descendants("patient")
where item.Element("name").Value == "Jhon"
select item).FirstOrDefault();
then update it using SetElementValue() method.
//Updated Xml
<?xml version="1.0" encoding="utf-8"?>
<patients>
<patient>
<regNo>2012/Mar/003</regNo>
<name>Jhon</name>
<add>New Address</add>
<mobile>0000</mobile>
<stay>2</stay>
<costofroom>100</costofroom>
<total>200</total>
</patient>
</patients>
Reference:
Update XML with C# using Linq
I would take the xml serialization/deserialization route to solve this:
http://support.microsoft.com/kb/815813
How to Deserialize XML document
That way you can work with objects and not have to parse xml files manually.
If you're using .NET 3.5 onward you can use the XDocument class like the following. I'm assuming your content is in a .xml file.
XDocument xdoc = XDocument.Load(#"C:\Tmp\test.xml");
//this would ensure you get the right node and set its text content/value
xdoc.Element("patients")
.Element("patient").Element("add").Value = "some new address?";
xdoc.Save(#"C:\Tmp\test.xml");
The file test.xml would change to:
<patients>
<patient>
<regNo>2012/Mar/003</regNo>
<name>Jhon</name>
<add>some new address?</add>
<mobile>0000</mobile>
<stay>2</stay>
<costofroom>100</costofroom>
<total>200</total>
</patient>
</patients>