I'm currently doing a XML file that includes the "name" of the city, the "region", "lat" latitude and "lng".
Here is my Code:
XmlDocument XmlFile = new XmlDocument();
try {
XmlFile.Load("..\\..\\liste.xml");
}
catch (Exception ex)
{
Console.WriteLine("Erreur" + ex.Message);
};
XmlNodeList MyNodeXML = XmlFile.GetElementsByTagName("city");
foreach (XmlNode unNode in MyNodeXML)
{
string nomVille = unNode.Attributes[0].Value;
string lat = unNode.Attributes[1].Value;
string lng = unNode.Attributes[2].Value;
listeCooVilles.Add(nomVille, new PointF(float.Parse(lat), float.Parse(lng)));
}
Where listeCooVilles is a Dictionnary.
Here is my XML: I did a sample for test:
<?xml version="1.0" encoding="UTF-8"?>
<cities>
<city>
<name>Abercorn</name>
<region>Montérégie</region>
<lat>45.032999</lat>
<lng>-72.663057</lng>
</city>
<cities>
I saw many post doing the same as above in StackOverflow, but I still get an IndexOutOfRange Exception on the line
string nomVille = unNode.Attributes[0].Value;
Can someone help? Thanks!
The element has no attributes - only sub-elements. Attributes are name=value pairs at the same level as the element. E.g.
<?xml version="1.0" encoding="UTF-8"?>
<cities>
<city name="Abercorn" region="Montérégie" lat="45.032999" lng="-72.663057" />
<city name="Granby" region="Montérégie" lat="45.4" lng="-72.733333" />
</cites>
Nesting elements (as you have done originally) and using attributes (as you've coded for) are both equally valid ways of structuring your XML document.
As pointed our those are elements not attributes. Your code needs to change to this:
nomVille = unNode.Item["name"].Value
region = unNode.Item["region"].Value
lat = unNode.Item["lat"].Value
lng = unNode.Item["lng"].Value
None of the nodes in your XML sample have attributes, which is why the collection has null elements in it.
Try changing it to:
<?xml version="1.0" encoding="UTF-8"?>
<cities>
<city testAttr = "hello!">
<name>Abercorn</name>
<region>Montérégie</region>
<lat>45.032999</lat>
<lng>-72.663057</lng>
</city>
<cities>
The addition of the testAttr should provide a valid collection in unNode.Attributes.
You are using attributes in city tag but I think you should be using xml elements.
Related
I read multiple feed from many sources with C# Console, and i have this code where i load XML From sources:
XmlDocument doc = new XmlDocument();
doc.Load(sourceURLX);
XElement xdoc = XElement.Load(sourceURLX);
How to get enclosure url and show as variable?
If I understand your question correctly (I'm making a big assumption here) - you want to select an attribute from the root (or 'enclosing') tag, named 'url'?
You can make use of XPath queries here. Consider the following XML:
<?xml version="1.0" encoding="utf-8"?>
<root url='google.com'>
<inner />
</root>
You could use the following code to retrieve 'google.com':
String query = "/root[1]/#url";
XmlDocument doc = new XmlDocument();
doc.Load(sourceURLX);
String value = doc.SelectSingleNode(query).InnerText;
Further information about XPath syntax can be found here.
Edit: As you stated in your comment, you are working with the following XML:
<item>
<description>
</description>
<enclosure url="blablabla.com/img.jpg" />
</item>
Therefore, you can retrieve the url using the following XPath query:
/item[1]/enclosure[1]/#url
With xml like below
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>title</title>
<link>https://www.link.com</link>
<description>description</description>
<item>
<title>RSS</title>
<link>https://www.link.com/xml/xml_rss.asp</link>
<description>description</description>
<enclosure url="https://www.link.com/media/test.wmv"
length="10000"
type="video/wmv"/>
</item>
</channel>
</rss>
You will get url by reading attribute
var document = XDocument.Load(sourceURLX);
var url = document.Root
.Element("channel")
.Element("item")
.Element("enclosure")
.Attribute("url")
.Value;
To get multiple urls
var urls = document.Descendants("item")
.Select(item => item.Element("enclosure").Attribute("url").Value)
.ToList();
Using foreach loop
foreach (var item in document.Descendants("item"))
{
var title = item.Element("title").Value;
var link = item.Element("link").Value;
var description = item.Element("description").Value;
var url = item.Element("enclosure").Attribute("url").Value;
// save values to database
}
This question already has answers here:
how to remove all the childnodes of the specified xmlnode in C# 4.0?
(6 answers)
Closed 5 years ago.
I have the following XML structure:
XML
<?xml version="1.0" encoding="utf-8" ?>
<Users>
</Users>
At some point, the <Users> gets filled up with different users, but I want to be able to delete them all in a single, simple function.
Attempt
/// <summary>
/// Removes all nodes from XML creds file on application close
/// </summary>
public static void RemoveXMLData()
{
string xmlPath = Path.Combine(Environment.CurrentDirectory, #"Data\Credential.xml");
XDocument document = XDocument.Load(xmlPath);
document.RemoveNodes();
}
This doesn't seem to be working. I've done the following as well:
Attempt #2
string xmlPath = Path.Combine(Environment.CurrentDirectory, #"Data\Credential.xml");
XDocument document = XDocument.Load(xmlPath);
foreach (var node in document.Descendants("Users"))
{
node.Remove();
}
But this yields an exception error.
At the end of the day, I just want to get back to square one with the following file data:
<?xml version="1.0" encoding="utf-8" ?>
<Users>
</Users>
This should work fine:
XDocument document = XDocument.Load(xmlPath);
document.Descendants("Users").Elements().Remove();
As suggested by #Cory, Alternative and faster approach would be:
document.Root.Elements().Remove();
It probably blows up on the second attempt as you are iterating the collection you remove from. Try this.
string xmlPath = Path.Combine(Environment.CurrentDirectory, #"Data\Credential.xml");
XDocument document = XDocument.Load(xmlPath);
var nodes = document.Descendants("Users");
while(nodes.Count > 0)
{
nodes[0].Remove();
}
I'm getting this XML structure from an ASMX web service.
<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfSecurityUser xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://sales.newsite.com/">
<SecurityUser>
<id>AAA1D75</id>
<code />
<lastName>Thumb</lastName>
<firstName>Tom</firstName>
<middleInitial />
</SecurityUser>
</ArrayOfSecurityUser>
How do I parse it to get the full name using C# ASP.NET?
I have tried the following:
XDocument x = XDocument.Load("GetUserInfo.xml");
XNamespace ns = "http://sales.newsite.com/";
but I don't know how to parse it.
After that point all you have to do is read the elements and format the string such as:
string fullname = string.Format("{0} {1} {2}",
x.Descendants(ns + "firstName").First().Value,
x.Descendants(ns + "middleInitial").First().Value,
x.Descendants(ns + "lastName").First().Value);
This is assuming there is only one SecurityUser. If there are multiple entries, instead you have to loop through instead of getting the first one.
I have below a xml file with the below format:
<?xml version="1.0" encoding="utf-8" ?>
<Root>
<Countries>
<country>India</country>
<country>USA</country>
<country>UK</country>
</Countries>
</Root>
string newCountry="UAE"
I want to insert this "UAE" country to the above xml file, before that I want to check whether "UAE" is already exists in the xml. If not exists then only want to insert otherwise no operation. How can I do this?
Like this:
XDocument xml = XDocument.Load("path_to_file");
string newCountry = "UAE";
XElement countries = xml.Descendants("Countries").First();
XElement el = countries.Elements().FirstOrDefault(x => x.Value == newCountry);
if (el == null)
{
el = new XElement("country");
el.Value = newCountry;
countries.Add(el);
}
//Console.WriteLine(countries.ToString());
The easiest way would probably be to read the xml into C# objects, check for the existance of UAE, potentially add it, and write the objects back to XML.
I am trying to parse somewhat standard XML documents that use a schema called MARCXML from various sources.
Here are the first few lines of an example XML file that needs to be handled...
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<marc:collection xmlns:marc="http://www.loc.gov/MARC21/slim" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd">
<marc:record>
<marc:leader>00925njm 22002777a 4500</marc:leader>
and one without namespace prefixes...
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<collection xmlns="http://www.loc.gov/MARC21/slim">
<record>
<leader>01142cam 2200301 a 4500</leader>
Key point: in order to get the XPaths to resolve further along in the program I have to go through a regex routine to add the namespaces to the NameTable (which doesn't add them by default). This seems unnecessary to me.
Regex xmlNamespace = new Regex("xmlns:(?<PREFIX>[^=]+)=\"(?<URI>[^\"]+)\"", RegexOptions.Compiled);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlRecord);
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmlDoc.NameTable);
MatchCollection namespaces = xmlNamespace.Matches(xmlRecord);
foreach (Match n in namespaces)
{
nsMgr.AddNamespace(n.Groups["PREFIX"].ToString(), n.Groups["URI"].ToString());
}
The XPath call looks something like this...
XmlNode leaderNode = xmlDoc.SelectSingleNode(".//" + LeaderNode, nsMgr);
Where LeaderNode is a configurable value and would equal "marc:leader" in the first example and "leader" in the second example.
Is there a better, more efficient way to do this? Note: suggestions for solving this using LINQ are welcome, but I would mainly like to know how to solve this using XmlDocument.
EDIT: I took GrayWizardx's advice and now have the following code...
if (LeaderNode.Contains(":"))
{
string prefix = LeaderNode.Substring(0, LeaderNode.IndexOf(':'));
XmlNode root = xmlDoc.FirstChild;
string nameSpace = root.GetNamespaceOfPrefix(prefix);
nsMgr.AddNamespace(prefix, nameSpace);
}
Now there's no more dependency on Regex!
If you know there is going to be a given element in the document (for instance the root element) you could try using GetNamespaceOfPrefix.