What's the difference using root node to select and using document object to select nodes?
Which way is preferred.
For example,
1.
XmlDocument Doc = new XmlDocument();
Doc.Load(mem);
XmlNodeList nodeList = Doc.SelectNodes(#"//#id");
2.
XmlDocument Doc = new XmlDocument();
Doc.Load(mem);
XmlElement root = Doc.DocumentElement;
XmlNodeList nodeList = root.SelectNodes(#"//#id");
In fact, I never got any differences. And use just
Doc.SelectNodes(#"//#id");
because if document's root exists
bool b = Doc.OuterXml == Doc.DocumentElement.OuterXml; // true
Since XPath's // expression always matches from the document root, the result will be the same whether you start from the document root or from its documentElement.
So I guess you're better off using the shorter Doc.SelectNodes("//#id"); syntax.
The root of an XML document contains its document element at least, but it may also contain processing instructions and comments. For instance, in this XML document:
<!-- This is a child of the root -->
<document_element>
<!-- This is a child of the document element -->
<document_element>
<!-- This is also a child of the root -->
the root has three child nodes, one of which is its top-level element. In this case, this:
XmlNodeList comments = doc.SelectNodes("comment()");
and this:
XmlNodeList comments = doc.DocumentElement.SelectNodes("comment()");
return totally different results.
Related
i've programmically written an xml document to store some data and when i try to load it back into my application in a different area all of my Xmlnodes are returning null even though the node name i've given it is identical. This is preventing me from extracting the innertext of each node.
Question:
What am i missing that is preventing me from reading this xml document
Code:
var xmlDocument = new XmlDocument();
xmlDocument.Load(#"\\mi\dfs\shared\Everyone\The Guy Technology\cavanaugh\OutageInformationDocument.xml");
XmlNode title = xmlDocument.SelectSingleNode("TitleTextvariable");
XmlNode type = xmlDocument.SelectSingleNode("TypeTextvaraible");
XmlNode information = xmlDocument.SelectSingleNode("InformationText");
XmlNode conference = xmlDocument.SelectSingleNode("ConferenceText");
XmlNode steps = xmlDocument.SelectSingleNode("StepsText");
XmlNode eta = xmlDocument.SelectSingleNode("EtaText");
XmlNode phone = xmlDocument.SelectSingleNode("PhoneMessageText");
XmlNode banner = xmlDocument.SelectSingleNode("BannerText");
XML Example:
<OutageInfo>
<OutageInformation>
<OutageInfoitems>
<TitleTextvariable>title text</TitleTextvariable>
<TypeTextvaraible>info</TypeTextvaraible>
<InformationText>this is a test of the outage information</InformationText>
<ConferenceText>information</ConferenceText>
<StepsText>resolve it in this way</StepsText>
<EtaText>30 minutes</EtaText>
<PhoneMessageText>There is currently a phone message up</PhoneMessageText>
<BannerText>There is not currently a banner posted</BannerText>
</OutageInfoitems>
</OutageInformation>
</OutageInfo>
You could use XElement:
var xml = XElement.Load(pathToFile);
var infoItem = xml.Descendants("OutageInfoitems").First();
var title = (string)infoItem.Element("TitleTextvariable");
The casting element to string (in the last line) is preferable way, because if there's no such element, then title will be null rather throwing exception.
The method you are using, XmlNode.SelectSingleNode(string xpath), selects the first XmlNode that matches the XPath expression passed in as the argument value.
Thus you need to use the XPath recursive descent operator // to descend your XML node hierarchy to pick out deeply nested nodes:
XmlNode title = xmlDocument.SelectSingleNode("//TitleTextvariable");
XmlNode type = xmlDocument.SelectSingleNode("//TypeTextvaraible");
XmlNode information = xmlDocument.SelectSingleNode("//InformationText");
XmlNode conference = xmlDocument.SelectSingleNode("//ConferenceText");
XmlNode steps = xmlDocument.SelectSingleNode("//StepsText");
XmlNode eta = xmlDocument.SelectSingleNode("//EtaText");
XmlNode phone = xmlDocument.SelectSingleNode("//PhoneMessageText");
XmlNode banner = xmlDocument.SelectSingleNode("//BannerText");
For more see Context for XPath Expressions:
The evaluation of an XPath expression depends on the context against which the expression operates. The context consists of the node against which the expression is evaluated and its associated environment, which includes the following...
Recursive descent
An expression that uses the double forward slash (//) indicates a search that can include zero or more levels of hierarchy. When this operator appears at the beginning of the pattern, the context is relative to the root of the document.
Working .Net fiddle.
I have an XML file that contains multiple URLs for different image file sizes, and I'm trying to get a single url to load into a picture box. My issue is that the child nodes are named similarly, and the parent nodes are named similarly as well. For example, I want to pull the first medium image (ending in SL160_.jpg). See below for XML code
<Items>
<SmallImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL._SL75_.jpg</URL>
</SmallImage>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL._SL160_.jpg</URL>
</MediumImage>
<LargeImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.jpg</URL>
</LargeImage>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL._SL162_.jpg</URL>
</MediumImage>
<LargeImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.jpg</URL>
</LargeImage>
</Items>
I've tried using GetElementsByTag, as well as trying to call something like doc.SelectSingleNode("LargeImage").SelectSingleNode("URL").InnerText, and GetElementByID. All of these have given me an Object set to null reference exception.
What can I do to specify that I want the url from the first found MediumImage node?
Use LinqToXMLïĵIt is rather simple
string xml = #"<Items>
<SmallImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL._SL75_.jpg</URL>
</SmallImage>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.01_SL160_.jpg</URL>
</MediumImage>
<LargeImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.jpg</URL>
</LargeImage>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.02_SL162_.jpg</URL>
</MediumImage>
<LargeImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.jpg</URL>
</LargeImage>
</Items>";
XElement root = XElement.Parse(xml);
var ele = root.Elements("MediumImage").Where(e => e.Element("URL").Value.EndsWith("SL160_.jpg")).FirstOrDefault();
Console.WriteLine(ele);
In addition to Sky Fang's answer, I think the OP wants this:
var firstMedImg = root.Elements("MediumImage").First();
var imgUrl = firstMedImg.Element("URL").Value;
XmlDocument doc = new XmlDocument();
// PATH TO YOUR DOCUMENT
doc.Load("daco.xml");
// Select LIST ALL ELEMENTS SmallImage,MediumImage,LargeImage
XmlNodeList listOfAllImageElements = doc.SelectNodes("/Items/*");
foreach (XmlNode imageElement in listOfAllImageElements)
{
// Select URL ELEMENT
XmlNode urlElement= node.SelectSingleNode("URL");
System.Console.WriteLine(urlElement.InnerText);
}
Console.ReadLine();
If you want to select multiple url's
XmlDocument doc = new XmlDocument();
// PATH TO YOUR DOCUMENT
doc.Load("daco.xml");
// Select LIST ALL ELEMENTS SmallImage,MediumImage,LargeImage
XmlNodeList listOfAllImageElements = doc.SelectNodes("/Items/*");
foreach (XmlNode imageElement in listOfAllImageElements)
{
// Select URL's ELEMENTs
XmlNodeList listOfAllUrlElements = imageElement.SelectNodes("URL");
foreach (XmlNode urlElement in listOfAllUrlElements)
{
System.Console.WriteLine(urlElement.InnerText);
}
}
Console.ReadLine();
if you have specific namespace in your xml file
XmlDocument doc = new XmlDocument();
doc.Load("doc.xml");
XmlNamespaceManager man = new XmlNamespaceManager(doc.NameTable);
// reaplace http://schemas.microsoft.com/vs/2009/dgml with your namespace
man.AddNamespace("x", "http://schemas.microsoft.com/vs/2009/dgml");
// next you have to use x: in your path like this
XmlNodeList node = doc.SelectNodes("/x:Items/x:*, man);
I work with three kinds of XML files :
Type A:
<?xml version="1.0" encoding="UTF-8"?>
<nfeProc versao="2.00" xmlns="http://www.portalfiscal.inf.br/nfe">
</nfeProc>
Tyepe B:
<?xml version="1.0" encoding="UTF-8"?>
<cancCTe xmlns="http://www.portalfiscal.inf.br/cte" versao="1.04">
</cancCTe>
Type C:]
<?xml version="1.0" encoding="UTF-8"?>
<cteProc xmlns="http://www.portalfiscal.inf.br/cte" versao="1.04">
</cteProc>
I have try with this code to read the first node :
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"C:\crruopto\135120068964590_v01.04-procCTe.xml");
XmlNodeList ml = xmlDoc.GetElementsByTagName("*");
XmlElement root = xmlDoc.DocumentElement;
exti = root.ToString();
but dont return anything i want to read the first node , need to know if the file is nfeProc ,canCTE or cteProc
The second question is how i get the value from "value" in the same tag???
Thanks
From this post:
//Root node is the DocumentElement property of XmlDocument
XmlElement root = xmlDoc.DocumentElement
//If you only have the node, you can get the root node by
XmlElement root = xmlNode.OwnerDocument.DocumentElement
I would suggest using XPath. Here's an example where I read in the XML content from a locally stored string and select whatever the first node under the root is:
XmlDocument doc = new XmlDocument();
doc.Load(new StringReader(xml));
XmlNode node = doc.SelectSingleNode("(/*)");
If you aren't required to use the XmlDocument stuff, then Linq is your friend.
XDocument doc = XDocument.Load(#"C:\crruopto\135120068964590_v01.04-procCTe.xml");
XElement first = doc.GetDescendants().FirstOrDefault();
if(first != null)
{
//first.Name will be either nfeProc, canCTE or cteProc.
}
Working with Linq to XML is the newest and most powerful way of working with XML in .NET and offers you a lot more power and flexibility than things like XmlDocument and XmlNode.
Getting the root node is very simple:
XDocument doc = XDocument.Load(#"C:\crruopto\135120068964590_v01.04-procCTe.xml");
Console.WriteLine(doc.Root.Name.ToString());
Once you have constructed an XDocument you don't need to use any LINQ querying or special checking. You simply pull the Root property from the XDocument.
Thanks i have solved this way the first part
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(nomear);
XmlNodeList ml = xmlDoc.GetElementsByTagName("*");
XmlNode primer = xmlDoc.DocumentElement;
exti = primer.Name;
First, to be clear, you're asking about the root element, not the root node.
You can use an XmlReader to avoid having to load large documents completely into memory. See my answer to a how to find the root element at https://stackoverflow.com/a/60642354/1307074.
Second, once the reader is referencing the element, you can use the reader's Name property to get the qualified tag name of the element. You can get the value as a string using the Value property.
I have two XmlDocuments. Something like:
<document1>
<inner />
</document1>
and
<document2>
<stuff/>
</document2>
I want to put document2 inside of the inner node of document1 so that I end up with a single docement containing:
<document1>
<inner>
<document2>
<stuff/>
</document2>
</inner>
</document1>
Here's the code...
XmlDocument document1, document2;
// Load the documents...
XmlElement xmlInner = (XmlElement)document1.SelectSingleNode("/document1/inner");
xmlInner.AppendChild(document1.ImportNode(document2.DocumentElement, true));
You can, but effectively a copy will be created. You have to use XmlNode node = document1.ImportNode(document2.RootElement), find the node and add node as a child element.
Example on msdn: http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.importnode.aspx
No. You can only have on XmlDocument in an XML DOM. What you want to do is get the DocumentElement associated with document2 and append that XmlElement as a child to the XmlElement.
Using C#
How do you remove a specific node from an XMLDocument using XPATH?
If you want to delete nodes, that are not direct children of the documents root, you can do this:
XmlDocument doc = new XmlDocument();
// ... fill or load the XML Document
XmlNode childNode = doc.SelectSingleNode("/rootnode/childnode/etc"); // apply your xpath here
childNode.ParentNode.RemoveChild(childNode);
Here you go. ChildNodeName, could be just the node name or an XPath query.
XmlDocument doc = new XmlDocument();
// Load you XML Document
XmlNode childNode = doc.SelectSingleNode(childNodeName);
// Remove from the document
doc.RemoveChild(childNode);
There is a different way using Linq, but I guessed you were using .NET 2.0
XPath can only select nodes from a document, not modify the document.