how to add Namespace and Declaration to the existing xml.
My XML
<Order>
<child1></child1>
</Order>
Expected
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<Order xmlns="http://a.com/a">
<child1></child>
</Order>
Assuming you're only changing the element namespaces and ignoring any attributes, you can parse this using LINQ to XML and then change every element's qualified name:
var doc = XDocument.Parse(xml);
XNamespace ns = "http://a.com/a";
foreach (var element in doc.Descendants())
{
element.Name = ns + element.Name.LocalName;
}
Related
I am trying to modify the following XML doc (MRE) using Linq to XML:
Move the school name and address one step higher or at the level of its parent—school element.
At the same time, change its name to <School_Name> and <School_Address>.
ORIGINAL
<?xml version="1.0" encoding="utf-8"?>
<GreatGrandParent>
<GrandParent>
<Parent>
<Child>
<Name>John</Name>
<Address>California</Address>
<Sex>Male</Sex>
<Age>18</Age>
<School>
<Name>Cool School</Name>
<Address>California</Address>
</School>
</Child>
<Child>
<Name>Mary</Name>
<Address>New Orleans</Address>
<Sex>Female</Sex>
<Age>16</Age>
<School>
<Name>Pretty School</Name>
<Address>New Orleans</Address>
</School>
</Child>
<Parent>
<GrandParent>
<GreatGrandParent>
TARGET MODIFICATION
<?xml version="1.0" encoding="utf-8"?>
<GreatGrandParent>
<GrandParent>
<Parent>
<Child>
<Name>John</Name>
<Address>California</Address>
<Sex>Male/Sex>
<Age>18</Age>
<School_Name>Cool School</School_Name>
<School_Address>California</School_Address>
</Child>
<Child>
<Name>Mary</Name>
<Address>New Orleans</Address>
<Sex>Female/Sex>
<Age>16</Age>
<School_Name>Pretty School</School_Name>
<School_Address>New Orleans</School_Address>
</Child>
<Parent>
<GrandParent>
<GreatGrandParent>
HERE'S WHAT I HAVE DONE SO FAR:
XDocument doc = XDocument.Load(#"D:\Xml\Childs Profile.xml");
XElement root = doc.XPathSelectElement("//Parent");
IEnumerable<XElement> rootlists = root.Descendants("Child").ToList();
foreach (var rootlist in rootlists)
{
XElement lists = root.Element("Child");
XElement name = root.Element("Child").Element("School").Element("Name");
XElement address = root.Element("Child").Element("School").Element("Address");
list.AddFirst(name);
list.AddFirst(address);
XElement school = root.Element("Child").Element("School");
school.Remove();
}
doc.Save(#"D:\Xml\Childs Profile.xml");
ISSUES: The foreach above does not move to next child.
PENDING: Change the XName to <School_Name> and <School_Address> either before or after moving.
You can try this:
XDocument doc = XDocument.Load(#"the.xml");
var child = doc.Descendants("Child");
var school = child.Elements("School");
string name = $"{school.First().Name}_{school.Elements("Name").First().Name}";
string address = $"{school.First().Name}_{school.Elements("Address").First().Name}";
foreach (var s in school)
{
s.Parent.Add(new XElement(name, s.Element("Name").Value));
s.Parent.Add(new XElement(address, s.Element("Address").Value));
}
school.Remove();
doc.Save(#"out.xml");
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.
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
<?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....