How do I get a NameTable from an XDocument? - c#

How do I get a NameTable from an XDocument?
It doesn't seem to have the NameTable property that XmlDocument has.
EDIT: Judging by the lack of an answer I'm guessing that I may be missing the point.
I am doing XPath queries against an XDocument like this...
document.XPathSelectElements("//xx:Name", namespaceManager);
It works fine but I have to manually add the namespaces I want to use to the XmlNamespaceManager rather than retrieving the existing nametable from the XDocument like you would with an XmlDocument.

You need to shove the XML through an XmlReader and use the XmlReader's NameTable property.
If you already have Xml you are loading into an XDocument then make sure you use an XmlReader to load the XDocument:-
XmlReader reader = new XmlTextReader(someStream);
XDocument doc = XDocument.Load(reader);
XmlNameTable table = reader.NameTable;
If you are building Xml from scratch with XDocument you will need to call XDocument's CreateReader method then have something consume the reader.
Once the reader has be used (say, by loading another XDocument, or better: some do-nothing sink which just causes the reader to run through the XDocument's contents) you can retrieve the NameTable.

I did it like this:
//Get the data into the XDoc
XDocument doc = XDocument.Parse(data);
//Grab the reader
var reader = doc.CreateReader();
//Set the root
var root = doc.Root;
//Use the reader NameTable
var namespaceManager = new XmlNamespaceManager(reader.NameTable);
//Add the GeoRSS NS
namespaceManager.AddNamespace("georss", "http://www.georss.org/georss");
//Do something with it
Debug.WriteLine(root.XPathSelectElement("//georss:point", namespaceManager).Value);

I have to manually add the namespaces I want to use to the
XmlNamespaceManager rather than retrieving the existing nametable from
the XDocument like you would with an XmlDocument.
XDocument project = XDocument.Load(path);
//Or: XDocument project = XDocument.Parse(xml);
var nsMgr = new XmlNamespaceManager(new NameTable());
//Or: var nsMgr = new XmlNamespaceManager(doc.CreateReader().NameTable);
nsMgr.AddNamespace("msproj", "http://schemas.microsoft.com/developer/msbuild/2003");
var itemGroups = project.XPathSelectElements(#"msproj:Project/msproj:ItemGroup", nsMgr).ToList();

It can also be done by XPathNavigator. Can be useful when you know neither Xml file Encoding nor namespace prefixes.
XDocument xdoc = XDocument.Load(sourceFileName);
XPathNavigator navi = xdoc.Root.CreateNavigator();
XmlNamespaceManager xmlNSM = new XmlNamespaceManager(navi.NameTable);
//Get all the namespaces from navigator
IDictionary<string, string> dict = navi.GetNamespacesInScope(XmlNamespaceScope.All);
//Copy them into Manager
foreach (KeyValuePair<string, string> pair in dict)
{
xmlNSM.AddNamespace(pair.Key, pair.Value);
}

Related

Change case in First node in XmlDocument

I have this XML:
<Feedback>
<Officer>Officer</Officer>
<Answers>My text</Answers>
<Date>20190917</Date>
</Feedback>
I want XML to look like this: (Lowercase first letter in main tag)
<feedback>
<Officer>Officer</Officer>
<Answers>My text</Answers>
<Date>20190917</Date>
</feedback>
How to do it using XMLDocument? I can't access this item
If using XmlDocument is not a hard requirement you can do it with linq fairly easily.
You can create a new XML document with the root node named how you want it then loop through the child nodes of the original and add them to your new XML object.
A simple example:
XDocument xDocument = XDocument.Parse("<Feedback><Officer>Officer</Officer><Answers>My text</Answers><Date>20190917</Date></Feedback>");
XDocument newDoc = new XDocument();
XElement rootElement = new XElement("feedback");
newDoc.Add(rootElement);
foreach (var node in xDocument.Root.Elements())
{
newDoc.Root.Add(node);
}
Console.WriteLine(newDoc);
Console.ReadLine();
However here is an example using XmlDocument if you really need to use that:
XmlDocument oldDoc = new XmlDocument();
XmlDocument newXmlDoc = new XmlDocument();
oldDoc.LoadXml("<Feedback><Officer>Officer</Officer><Answers>My text</Answers><Date>20190917</Date></Feedback>");
XmlElement newRoot = newXmlDoc.CreateElement("feedback");
newXmlDoc.AppendChild(newRoot);
XmlNode root = newXmlDoc.DocumentElement;
foreach (XmlNode node in oldDoc.FirstChild.ChildNodes)
{
XmlElement elem = newXmlDoc.CreateElement(node.Name);
elem.InnerText = node.InnerText;
//Add the node to the document.
root.AppendChild(elem);
}
XmlTextWriter writer = new XmlTextWriter(Console.Out);
writer.Formatting = Formatting.Indented;
newXmlDoc.WriteTo(writer);
writer.Flush();
Console.WriteLine();
Console.ReadLine();
In this case, you can change the name directly:
var XML = ""; // Your XML in string
var tempDoc = new XmlDocument();
tempDoc.LoadXml(XML);
tempDoc.InnerXml = tempDoc.InnerXml.Replace("Feedback>", "feedback>");
XML = tempDoc.OuterXml;
This is a simple way to change the name
Do not use in other situations because various errors may arise, e.g another element may end in the same name

get grandson text using xml document in c#

I'm using XmlDocument in C# and I would like to know how to get grandson data of the root?
<tRoot>
<One>
<a>15</a>
<b>11</b>
<c>1</c>
<d>11.35</d>
<e>0</e>
<f>289</f>
</One>
<Two>
<a>0</a>
<b>11</b>
<c>1</c>
<d>0.28</d>
<e>0</e>
<f>464</f>
</Two>
</tRoot>
and I want the ability to get a of One and also a of Two
I tried:
var doc = new XmlDocument();
doc.Load(Consts.FileConst);
var docXml = doc["One"];
if (docXml != null)
{
float valFromXml = float.Parse(docXml["a"].InnerText);
}
The issue is that docXml is null
Any assitance?
As suggested above, XDocument would be a better alternative. If, however, you still want to use XmlDocument, you can iterate through the children using
var doc = new XmlDocument();
doc.Load(Consts.FileConst);
foreach(XmlNode xmlNode in doc.DocumentElement.ChildNodes) {
//access a/b/c/d/e using:
xmlNode.ChildNodes[0].InnerText; //for a
xmlNode.ChildNodes[1].InnerText; //for b
}
Try this:
XmlDocument d = new XmlDocument();
d.LoadXml("<tRoot><One><a>15</a><b>11</b><c>1</c><d>11.35</d><e>0</e><f>289</f></One><Two><a>0</a><b>11</b><c>1</c><d>0.28</d><e>0</e><f>464</f></Two></tRoot>");
XmlNodeList itemNodes = d.SelectNodes("//*/a");

How to update an XML file in C#

I am having an XML file. I would like to create a new node and append it at the end of the XML file and save it back to memory.
<IntCal>
<User>
<Date>12/09/2012</Date>
<Client>abcd</Client>
<Jewellery>Others</Jewellery>
<ROI>7.5</ROI>
<Description>Some Description</Description>
</User>
<IntCal>
I would like to create a new <User> element. Any idea how to do it.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlFile);
XmlNode root_node;
//XmlNodeList nodeList = xmlDoc.SelectNodes("/IntCal/User");
XmlDocument new_node = new XmlDocument();
root_node = xmlDoc.CreateElement("IntCal");
xmlDoc.AppendChild(root_node);
Thanks
Reference: http://msdn.microsoft.com/en-us/library/fw1ys7w6(v=vs.100).aspx
XmlElement elem = xmlDoc.CreateElement("User");
xmlDoc.DocumentElement.AppendChild(elem);
If you want to go the LINQ route, you could do:
XDocument xDoc = XDocument.Load(xmlFile);
xDoc.Element("IntCal")
.Add(new XElement("User"));
Personally, I'd opt for the XDocument and use LINQ but either way works.
Reference: http://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument.aspx
XmlDocument is an old school, why don't you use XDocument, simple and easy:
XDocument xDoc = XDocument.Load(xmlFile);
xDoc.Root.Add(new XElement("User",
new XElement("Client", "John"),
new XElement("Jewellery", "Others")));
xDoc.Save(xmlFile);
References:
XDocument or XmlDocument
Performance: XDocument versus XmlDocument

I need to convert an XML string into an XmlElement

I'm looking for the simplest way to convert a string containing valid XML into an XmlElement object in C#.
How can you turn this into an XmlElement?
<item><name>wrench</name></item>
Use this:
private static XmlElement GetElement(string xml)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
return doc.DocumentElement;
}
Beware!!
If you need to add this element to another document first you need to Import it using ImportNode.
Suppose you already had a XmlDocument with children nodes, And you need add more child element from string.
XmlDocument xmlDoc = new XmlDocument();
// Add some child nodes manipulation in earlier
// ..
// Add more child nodes to existing XmlDocument from xml string
string strXml =
#"<item><name>wrench</name></item>
<item><name>screwdriver</name></item>";
XmlDocumentFragment xmlDocFragment = xmlDoc.CreateDocumentFragment();
xmlDocFragment.InnerXml = strXml;
xmlDoc.SelectSingleNode("root").AppendChild(xmlDocFragment);
The Result:
<root>
<item><name>this is earlier manipulation</name>
<item><name>wrench</name></item>
<item><name>screwdriver</name>
</root>
Use XmlDocument.LoadXml:
XmlDocument doc = new XmlDocument();
doc.LoadXml("<item><name>wrench</name></item>");
XmlElement root = doc.DocumentElement;
(Or in case you're talking about XElement, use XDocument.Parse:)
XDocument doc = XDocument.Parse("<item><name>wrench</name></item>");
XElement root = doc.Root;
You can use XmlDocument.LoadXml() to do this.
Here is a simple examle:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml("YOUR XML STRING");
I tried with this snippet, Got the solution.
// Sample string in the XML format
String s = "<Result> No Records found !<Result/>";
// Create the instance of XmlDocument
XmlDocument doc = new XmlDocument();
// Loads the XML from the string
doc.LoadXml(s);
// Returns the XMLElement of the loaded XML String
XmlElement xe = doc.DocumentElement;
// Print the xe
Console.out.println("Result :" + xe);
If any other better/ efficient way to implement the same, please let us know.
Thanks & Cheers

Change XML root element name

I have XML stored in string variable:
<ItemMasterList><ItemMaster><fpartno>xxx</fpartno><frev>000</frev><fac>Default</fac></ItemMaster></ItemMasterList>
Here I want to change XML tag <ItemMasterList> to <Masterlist>. How can I do this?
System.Xml.XmlDocument and the associated classes in that same namespace will prove invaluable to you here.
XmlDocument doc = new XmlDocument();
doc.LoadXml(yourString);
XmlDocument docNew = new XmlDocument();
XmlElement newRoot = docNew.CreateElement("MasterList");
docNew.AppendChild(newRoot);
newRoot.InnerXml = doc.DocumentElement.InnerXml;
String xml = docNew.OuterXml;
I know i am a bit late, but just have to add this answer as no one seems to know about this.
XDocument doc = XDocument.Parse("<ItemMasterList><ItemMaster><fpartno>xxx</fpartno><frev>000</frev><fac>Default</fac></ItemMaster></ItemMasterList>");
doc.Root.Name = "MasterList";
Which returns the following:
<MasterList>
<ItemMaster>
<fpartno>xxx</fpartno>
<frev>000</frev>
<fac>Default</fac>
</ItemMaster>
</MasterList>
You can use LINQ to XML to parse the XML string, create a new root and add the child elements and attributes of the original root to the new root:
XDocument doc = XDocument.Parse("<ItemMasterList>...</ItemMasterList>");
XDocument result = new XDocument(
new XElement("Masterlist", doc.Root.Attributes(), doc.Root.Nodes()));
Using the XmlDocument way, you can do this as follows (and keep the tree intact):
XmlDocument oldDoc = new XmlDocument();
oldDoc.LoadXml("<ItemMasterList><ItemMaster><fpartno>xxx</fpartno><frev>000</frev><fac>Default</fac></ItemMaster></ItemMasterList>");
XmlNode node = oldDoc.SelectSingleNode("ItemMasterList");
XmlDocument newDoc = new XmlDocument();
XmlElement ele = newDoc.CreateElement("MasterList");
ele.InnerXml = node.InnerXml;
If you now use ele.OuterXml is will return: (you you just need the string, otherwise use XmlDocument.AppendChild(ele) and you will be able to use the XmlDocument object some more)
<MasterList>
<ItemMaster>
<fpartno>xxx</fpartno>
<frev>000</frev>
<fac>Default</fac>
</ItemMaster>
</MasterList>
As pointed by Will A, we can do it that way but for case where InnerXml equals the OuterXml the following solution will work out:
// Create a new Xml doc object with root node as "NewRootNode" and
// copy the inner content from old doc object using the LastChild.
XmlDocument docNew = new XmlDocument();
XmlElement newRoot = docNew.CreateElement("NewRootNode");
docNew.AppendChild(newRoot);
// The below line solves the InnerXml equals the OuterXml Problem
newRoot.InnerXml = oldDoc.LastChild.InnerXml;
string xmlText = docNew.OuterXml;

Categories

Resources