I want to remove parent elements from an XML structure if child is empty.
My XML:
<Customers>
<customer>
<Name>John</Name>
<Age>25</Age>
<Status>single</Status>
</Customer>
<customer>
<Name>Jack</Name>
<Age></Age>
<Status></Status>
</Customer>
</Customers>
Should become:
<Customers>
<customer>
<Name>John</Name>
<Age>25</Age>
<Status>single</Status>
</Customer>
</Customers>
my code :
XmlElement element3 = xmlDocument.CreateElement("Age");
element3.InnerText = str3;
element1.AppendChild((XmlNode)element3);
XmlElement element4 = xmlDocument.CreateElement("Status");
element4.InnerText = str4;
element1.AppendChild((XmlNode)element4);
How can I remove the parent "customer", if age and status child are empty?
You can use XPath syntax along with SelectNodes() method to get specific nodes from XmlDocument easily.
Example to select <Customer> elements having child node <Age> and <Status> empty, then remove those selected elements :
var nodes = xmlDocument.DocumentElement.SelectNodes("//Customer[Age = '' and Status = '']");
foreach (XmlElement node in nodes)
{
node.ParentNode.RemoveChild(node);
}
UPDATE :
It seems that you're the one that construct the XML. So i'd suggest to check if str3 and str4 are empty, and if they are remove corresponding <Customer> element :
if(string.IsNullOrEmpty(str3) && string.IsNullOrEmpty(str4))
{
element1.ParentNode.RemoveChild(element1);
}
I understand that you're creating a new file and adding each element after the validation. I think this should work for you:
XDocument input = XDocument.Load("customers.xml");
XDocument output = new XDocument();
output.Add(new XElement("Customers"));
IEnumerable<XElement> elements = input.Element("Customers").Elements("customer");
foreach (XElement el in elements)
{
string age = el.Element("Age").Value;
string status = el.Element("Status").Value;
if (age != "" || status != "")
{
output.Element("Customers").Add(el);
}
}
output.Save("customers.xml");
Related
So I have a program that reads all the name nodes in a XML file and adds these to a Combo Box. On a button click, it then takes this response and needs to get all the other data from the child nodes of the node the name is in.
The XML document:
<People>
<Person>
<Name>Greg</Name>
<Age>23</Age>
<Height>200</Height>
</Person>
<Person>
<Name>John</Name>
<Age>34</Age>
<Height>230</Height>
</Person>
</People>
What I've got so far:
XmlDocument Doc = new XmlDocument();
Doc.Load(FilePath);
foreach (XmlNode Node in Doc.SelectNodes("People/Person"))
{
comboBox1.Items.Add(Node.SelectSingleNode("Name").InnerText);
}
string RegPicked = comboBox1.SelectedItem.ToString();
foreach (XmlNode xNode in Doc.SelectNodes("People/Person"))
if (xNode.SelectSingleNode("Name").InnerText == RegPicked)
{
textBox1.Text = xNode.ParentNode.ChildNodes.ToString();
}
Doc.Save(FilePath);
When I run the code I just get "System.Xml.XmlChildNodes" in the text box.
I know I've done something wrong but I'm not sure what.
you have to distinguished child node:
textBox1.Text = xNode.ParentNode.ChildNodes.SelectSingleNode("age").InnerText;
Do this, you will get all the elements inside the parent of the node you are searching the value of.
string str = #"<People>
<Person>
<Name>Greg</Name>
<Age>23</Age>
<Height>200</Height>
</Person>
<Person>
<Name>John</Name>
<Age>34</Age>
<Height>230</Height>
</Person>
</People>";
XDocument xdoc = XDocument.Parse(str);
var xmlURL = (from el in xdoc.Descendants("Name")
where el.Value == "John"
select el.Parent).First().ToString();
How can I get the value of a Node in a XDocument when don't has more childs ?
<Contacts>
<Company>
<Name>Testing</Name>
<ID>123</ID>
</Company>
</Contacts>
In this case, I wanna get the value of the <Name> and <ID> element, because don't has child elements in them.
I'm trying the follow
protected void LeXMLNode(HttpPostedFile file)
{
XmlReader rdr = XmlReader.Create(file.FileName);
XDocument doc2 = XDocument.Load(rdr);
foreach (var name in doc2.Root.DescendantNodes().OfType<XElement>().Select(x => x.Name).Distinct())
{
XElement Contact = (from xml2 in doc2.Descendants(name.ToString())
where xml2.Descendants(name.ToString()).Count() == 0
select xml2).FirstOrDefault();
string nome = name.ToString();
}
}
but without success, because my foreach pass in all Elements and I wanna get just the value of Elements that don't has childs.
document.Root.Elements("Company").Elements()
.Where(item => !item.HasElements).ToList();
See XElement.HasElements: http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.haselements.aspx
I would like to filter with high performance XML elements from an XML document.
Take for instance this XML file with contacts:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="asistentes.xslt"?>
<contactlist evento="Cena Navidad 2010" empresa="company">
<contact type="1" id="1">
<name>Name1</name>
<email>xxxx#zzzz.es</email>
<confirmado>SI</confirmado>
</contact>
<contact type="1" id="2">
<name>Name2</name>
<email>xxxxxxxxx#zzzze.es</email>
<confirmado>Sin confirmar</confirmado>
</contact>
</contaclist>
My current code to filter from this XML document:
using System;
using System.Xml.Linq;
class Test
{
static void Main()
{
string xml = #" the xml above";
XDocument doc = XDocument.Parse(xml);
foreach (XElement element in doc.Descendants("contact")) {
Console.WriteLine(element);
var id = element.Attribute("id").Value;
var valor = element.Descendants("confirmado").ToList()[0].Value;
var email = element.Descendants("email").ToList()[0].Value;
var name = element.Descendants("name").ToList()[0].Value;
if (valor.ToString() == "SI") { }
}
}
}
What would be the best way to optimize this code to filter on <confirmado> element content?
var doc = XDocument.Parse(xml);
var query = from contact in doc.Root.Elements("contact")
let confirmado = (string)contact.Element("confirmado")
where confirmado == "SI"
select new
{
Id = (int)contact.Attribute("id"),
Name = (string)contact.Element("name"),
Email = (string)contact.Element("email"),
Valor = confirmado
};
foreach (var contact in query)
{
...
}
Points of interest:
doc.Root.Elements("contact") selects only the <contact> elements in the document root, instead of searching the whole document for <contact> elements.
The XElement.Element method returns the first child element with the given name. No need to convert the child elements to a list and take the first element.
The XElement and XAttribute classes provide a wide selection of convenient conversion operators.
You could use LINQ:
foreach (XElement element in doc.Descendants("contact").Where(c => c.Element("confirmado").Value == "SI"))
I have been trying to read an xml file. I have to extract value of nodes "Date" and "Name", but the problem is, they might appear at any level in XML hierarchy.
So when I try with this code,
XmlDocument doc = new XmlDocument();
doc.Load("test1.xml");
XmlElement root = doc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("//*");
string date;
string name;
foreach (XmlNode node in nodes)
{
date = node["date"].InnerText;
name = node["name"].InnerText;
}
and the XML file is ::
<?xml version="1.0" encoding="utf-8"?>
<root>
<child>
<name>Aravind</name>
<date>12/03/2000</date>
</child>
</root>
the above code errors out, as <name> and <date> are not immediate child Elements of root.
is it possible to assume that parent/root nodes are unknown and just with the name of the nodes, copy the values ??
Depending on the exception you are getting, this may or may not be the exact solution. However, I would definitely check that date and name exist before doing a .InnerText on them.
foreach (XmlNode node in nodes)
{
dateNode = node["date"];
if(dateNode != null)
date = dateNode.InnerText;
// etc.
}
I would read up on XPATH and XPATH for C# to do this more efficiently
http://support.microsoft.com/kb/308333
http://www.w3schools.com/XPath/xpath_syntax.asp
Here's a little method that should allow you to get the innerText easily.
function string GetElementText(string xml, string node)
{
XPathDocument doc = new XPathDocument(xml);
XPathNavigator nav = doc.CreateNavigator();
XPathExpression expr = nav.Compile("//" + node);
XPathNodeIterator iterator = nav.Select(expr);
while (iterator.MoveNext())
{
// return 1st but there could be more
return iterator.Current.Value;
}
}
Try to use LINQ:
string xml = #"<?xml version='1.0' encoding='utf-8'?>
<root>
<date>12/03/2001</date>
<child>
<name>Aravind</name>
<date>12/03/2000</date>
</child>
<name>AS-CII</name>
</root>";
XDocument doc = XDocument.Parse(xml);
foreach (var date in doc.Descendants("date"))
{
Console.WriteLine(date.Value);
}
foreach (var date in doc.Descendants("name"))
{
Console.WriteLine(date.Value);
}
Console.ReadLine();
The Descendants method allows you to get all the elements that have a specified name.
I need to delete specific employee node and also its child node based on the value of id.
For example, here I need to delete employee tag with id="2".
<company>
<employee>
<id>1</id>
<name>sa</name>
</employee>
<employee>
<id>2</id>
<name>ssa</name>
</employee>
</company>
Assuming you have loaded that into an XmlDocument named doc:
XmlElement el = (XmlElement)doc.SelectSingleNode("/company/employee[id=2]");
if(el != null) { el.ParentNode.RemoveChild(el); }
Try this one
XmlDocument xmlDoc = new XmlDocument();
XmlNode nodeToDelete = xmlDoc.SelectSingleNode("/root/XMLFileName[#ID="+nodeId+"]");
if (nodeToDelete != null)
{
nodeToDelete.ParentNode.RemoveChild(nodeToDelete);
}
xmlDoc.Save("XMLFileName.xml")