I have the following node in my xml file :
<PERSON>
<LEOKA_DATA> </LEOKA_DATA>
</PERSON>
I am not able to remove the LEOKA tag using the following code (snippet):
string file = CommonVariables.MainDir + #"\Schemas\RemoveEmptyTags.xsl";
try
{
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(tempFile); //tempfile is the xml file
XmlNodeList emptyElements = xmlDocument.SelectNodes(#"//*[not(node())]");
if (emptyElements != null)
for (int i = emptyElements.Count - 1; i >= 0; i--)
{
var parentNode = emptyElements[i].ParentNode;
if (parentNode != null)
{
if (emptyElements[i].Name != "LINE")
parentNode.RemoveChild(emptyElements[i]);
}
}
}
catch (FileNotFoundException ex)
{ **something here** }
However, the code above works if the node is like below (notice no space between start tag and end tag) :
<LEOKA></LEOKA>
I also tried using the following code but didn't work :
var doc = XDocument.Parse(tempfile);
var emptyElements = from descendant in doc.Descendants()
where string.IsNullOrWhiteSpace(descendant.Value)
select descendant;
emptyElements.Remove();
Any help would be really appreciated. Please let me know if you need more details. Thanks.
I would modify your XPath expression as follows:
XmlNodeList emptyElements = xmlDocument.SelectNodes(#"//*[not(node()[
not(self::text()[normalize-space() = ''])
])]");
In other words, exclude elements that have a child other than an empty text node, where "empty" means having no text value other than whitespace.
Related
I have been tasked with taking one XML file and converting it to a new XML I have no experience working with XML documents but I have been able to get some of the data from the first XML document using the code shown below. Note not all code is being shown just a small example.
XmlDocument rssXmlDoc = new XmlDocument();
// Load the RSS file from the RSS URL
rssXmlDoc.Load("https://agency.governmentjobs.com/jobfeed.cfm?agency=ocso");
// Setup name space
XmlNamespaceManager nsmgr = new XmlNamespaceManager(rssXmlDoc.NameTable);
nsmgr.AddNamespace("joblisting", "http://www.neogov.com/namespaces/JobListing");
// Parse the Items in the RSS file
XmlNodeList rssNodes = rssXmlDoc.SelectNodes("rss/channel/item/");
// Iterate through the items in the RSS file
foreach (XmlNode rssNode in rssNodes)
{
XmlNode rssSubNode = rssNode.SelectSingleNode("title");
string title = rssSubNode != null ? rssSubNode.InnerText : "";
using this code I am able to get most of the elements. I have run into a wall when trying to get data from a child element. The portion of the XML I cannot get is shown below.
<joblisting:department>Supply</joblisting:department>
<guid isPermaLink="true">https://www.governmentjobs.com/careers/ocso/Jobs/2594527</guid>
<joblisting:categories>
<joblisting:category xmlns:joblisting="http://www.neogov.com/namespaces/JobListing" xmlns:atom="http://www.w3.org/2005/Atom">
<CategoryCode>ClericalDataEntry</CategoryCode>
<Category>Clerical & Data Entry</Category>
</joblisting:category>
<joblisting:category
</joblisting:categories>
But I cannot get all of the data. How can I get the value for the element that starts with guid isPermaLink="true"
For the joblisting:categories I have used a foreach loop to read those values
foreach (var item in rssSubNode.SelectNodes("joblisting:categories", nsmgr))
{
rssSubNode = rssSubNode = rssNode.SelectSingleNode("joblisting:category", nsmgr);
string category = rssSubNode != null ? rssSubNode.InnerText : "";
}
How can read the values of those child elements?
To read guid node you can use the follow code. note that use selectSingleNode in node contains the "item" node.
public static void test() {
XmlDocument rssXmlDoc = new XmlDocument();
// Load the RSS file from the RSS URL
rssXmlDoc.Load("https://agency.governmentjobs.com/jobfeed.cfm?agency=ocso");
// Setup name space
XmlNamespaceManager nsmgr = new XmlNamespaceManager(rssXmlDoc.NameTable);
nsmgr.AddNamespace("joblisting", "http://www.neogov.com/namespaces/JobListing");
// Parse the Items in the RSS file
XmlNodeList rssNodes = rssXmlDoc.SelectNodes("rss/channel/item");
// Iterate through the items in the RSS file
foreach (XmlNode rssNode in rssNodes) {
var xmlnode = rssNode.SelectSingleNode("guid ");
System.Console.WriteLine("the value of guid is =>" + xmlnode.InnerText);
XmlNode rssSubNode = rssNode.SelectSingleNode("title");
string title = rssSubNode != null ? rssSubNode.InnerText : "";
}
}
I found this question:
How to remove an xml element from file?
Which seems to work fine if you know some info within the element you want to delete.
But I have a OnItemDeleting function in ASP.NET where I only have (I think) the Selected Index of the item in a ListView.
In my C# file I have defined two alternatives (A and B) as you can see, it looks like this:
System.Diagnostics.Debug.WriteLine("IN ON ITEM DELETING.");
ListView1.SelectedIndex = e.ItemIndex;
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(path);
XmlNodeList nodes = xmldoc.GetElementsByTagName("EmployeeInformation");
for (int i = 0; i < nodes.Count; i++)
{
if (i == ListView1.SelectedIndex)
{
nodes[i].RemoveChild(nodes[i]); // Alt. A
xmldoc.RemoveChild(nodes[i]); // Alt. B
break;
}
}
xmldoc.Save(path);
BindDatalist();
If I try something like A, I dont know how to replace the nodes in the XmlDocument with the nodes in the XmlNodeList, and if I do like B it just doesn't work and also its weird.
The XML file looks like this:
<EmployeeInformation>
<Details>
<Name>Goofy</Name>
<Emp_id>Goooof</Emp_id>
<Qualification>BBA</Qualification>
</Details>
<Details>
<Name>Donald</Name>
<Emp_id>Duck</Emp_id>
<Qualification>MTech</Qualification>
</Details>
<Details>
<Name>Donald</Name>
<Emp_id>Trump</Emp_id>
<Qualification>MCA</Qualification>
</Details>
</EmployeeInformation>
So lets say I want to remove the Donald Trump item by clicking a button next to it. The selectedIndex would be 2.
In your case looping XmlNodeList not required.
try this
XmlDocument doc = new XmlDocument();
doc.Load(path);
if (ListView1.SelectedIndex < doc.DocumentElement.ChildNodes.Count)
{
doc.DocumentElement.RemoveChild(doc.DocumentElement.ChildNodes[ListView1.SelectedIndex]);
doc.Save(path);
}
Specifying that the node to be deleted from the XlmNodeList is a parent node solved the problem:
ListView1.SelectedIndex = e.ItemIndex;
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(path);
XmlNodeList nodes = xmldoc.GetElementsByTagName("Details");
for (int i = 0; i < nodes.Count; i++)
{
if (i == e.ItemIndex)
{
nodes[i].ParentNode.RemoveChild(nodes[i]);
break;
}
}
xmldoc.Save(path);
BindDatalist();
I have the following XML:
<Root><Node1>node1 value</Node1><Node2>node2 value</Node2></Root>
I'd like to check if Root is the first node. If so, I then want to get the values for the to child nodes.
This XML is inside of an XElement. I've tried this:
xml.Element("Root")
but that returns null. If Root exist, shouldn't it return a non null value?
string xml = #"<Root><Node1>node1 value</Node1><Node2>node2 value</Node2></Root>";
XDocument doc = XDocument.Parse(xml);
var root = doc.Root;
if(root.Name == "Root")
{
foreach(var el in root.Descendants())
{
string nodeValue = el.Value;
}
}
You can check the name of the Root element from Root.Name. After that loop all elements in the root using doc.Root.Descendants().
Since xml is an instance of XElement, it already references the root element, which in this case named Root. Doing xml.Element("Root") will return result only if the <Root> element has another child <Root>.
I'd like to check if Root is the first node.
You can simply check the Name of the root element :
var raw = "<Root><Node1>node1 value</Node1><Node2>node2 value</Node2></Root>";
var xml = XElement.Parse(raw);
if (xml.Name.ToString() == "Root")
Console.WriteLine("Success");
else
Console.WriteLine("Fail");
Try this solution
XDocument doc = XDocument.Parse(#"<Root><Node1>node1value</Node1><Node2>node2value</Node2></Root>");
if(doc!=null)
{
if (doc.Root.Name.LocalName == "Root")
{
foreach (var i in doc.Descendants())
Console.WriteLine(i.Value);
}
}
I am trying to read the following file, I can read the attributes, but I can't go into the specific element (Address in this case) and read its elements based on the attribute of that (Address) element. Shortly I need to distinguish between work and home addresses. I need to do this with XMLReader class. Can you help?
<Address Label="Work">
<Name>Name1</Name>
<Street>PO 1</Street>
<City>City1</City>
<State>State 1</State>
</Address>
<Address Label="Home">
<Name>Name2</Name>
<Street>PO 2</Street>
<City>City2</City>
<State>State 2</State>
</Address>"
Okay, here are some notes to think about. XMLReader in the sense i understand you use it (with no code example) is that you iterate over the document, since the XMLReader is forward-only, and read-only.
Because of this you need to iterate until you find the node you need. In the example below i find the address element labeled "work" and extract that entire node. Then query on this node as you want.
using (var inFile = new FileStream(path, FileMode.Open))
{
using (var reader = new XmlTextReader(inFile))
{
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
if (reader.Name == "Address" && reader.GetAttribute(0) == "Work")
{
// Create a document, which will contain the address element as the root
var doc = new XmlDocument();
// Create a reader, which only will read the substree <Address> ... until ... </Address>
doc.Load(reader.ReadSubtree());
// Use XPath to query the nodes, here the "Name" node
var name = doc.SelectSingleNode("//Address/Name");
// Print node name and the inner text of the node
Console.WriteLine("Node: {0}, Inner text: {1}", name.Name, name.InnerText);
}
break;
}
}
}
}
Edit
Made an example that not uses LINQ
XML:
<Countries>
<Country name ="ANDORRA">
<state>Andorra (general)</state>
<state>Andorra</state>
</Country>
<Country name ="United Arab Emirates">
<state>Abu Z¸aby</state>
<state>Umm al Qaywayn</state>
</Country>
Java:
public void datass(string file)
{
string file = HttpContext.Current.Server.MapPath("~/App_Data/CS.xml");
XmlDocument doc = new XmlDocument();
if (System.IO.File.Exists(file))
{
//Load the XML File
doc.Load(file);
}
//Get the root element
XmlElement root = doc.DocumentElement;
XmlNodeList subroot = root.SelectNodes("Country");
for (int i = 0; i < subroot.Count; i++)
{
XmlNode elem = subroot.Item(i);
string attrVal = elem.Attributes["name"].Value;
Response.Write(attrVal);
XmlNodeList sub = elem.SelectNodes("state");
for (int j = 0; j < sub.Count; j++)
{
XmlNode elem1 = sub.Item(j);
Response.Write(elem1.InnerText);
}
}
}
Using XPath you can easily write concise expressions to navigate an XML document.
You would do something like
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(myXMLString);
XmlNode homeAddress = xDoc.SelectSingleNode("//Address[#Label='Work']");
Then do whatever you want with homeAddress.
Read more here on w3schools on XPath.
I have an xml file. I want to query a peer node in C#.
For ex: For a given input xml file as below,
i want to query the title using the artist as an input. How do i do this ??
i.e Input --> Pink Floyd, Output -----> Division Bell ..
<catalog>
<cd>
<title>Division Bell<title>
<artist>Pink Floyd<artist>
<price>29$<price>
</cd>
<cd>
<title>Relapse<title>
<artist>Eminem<artist>
<price>19$<price>
</cd>
</catalog>
You could use a XDocument:
using System;
using System.Linq;
using System.Xml.Linq;
class Program
{
static void Main()
{
var doc = XDocument.Load("test.xml");
var result =
(from cd in doc.Root.Descendants("cd")
let artist = cd.Element("artist")
let title = cd.Element("title")
where artist != null && title != null && artist.Value == "Pink Floyd"
select title.Value
).FirstOrDefault();
Console.WriteLine(result);
}
}
Its quite easy tor read xml in .net
XDocument loaded = XDocument.Load(#"C:\youxml.xml");
var query = from xElem in loaded.Descendants("cd")
where xElem.Element("artist").Value == "Eminem"
select new Friend
{
Title = xElem.Attribute("title").Value
};
Make use of Linq To XML or XLINQ will resolve you issue easily.
Also check this : http://msdn.microsoft.com/en-us/library/bb308960.aspx
You can also use XPath syntax.
here is an example:
string inputArtist = "Pink Floyd";
var doc = XDocument.Load("test.xml");
XmlNode cdTitleNode = doc.SelectSingleNode("//cd[artist='" + inputArtist + "']/title");
string outputTitle = cdTitleNode.InnerText;
There is an excellent XPATH simulator on http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm to try you Xpath expressions.
You can also found a good tutorial there, but a fast search on the web will result in many web pages explaining all about XPath usage and syntax.
Using XPath, you can return a match:
using System.Xml;
using System.Xml.XPath;
public string QuerySearch(string file, string artist) {
// create an XML Document and load the file
XmlDocument xd = new XmlDocument();
xd.Load(file);
// get the root xml element
XmlElement root = xd.DocumentElement;
// get the list of artists
XmlNodeList aristList = root.GetElementsByTagName("artist");
// get the list of titles's
XmlNodeList titleList = root.GetElementsByTagName("title");
// find match
for (int i = 0;i < aristList.Count; i++) {
if (aristList.Item(i).InnerText == artist) {
return titleList.Item(i).InnerText
}
}
return "no match found.";
}