I have the below piece of code that accepts an XMLDocument object and a xml of the format mentioned below the code. I want to read the values of 4 tags present in the bouding box:
SouthLatitude, etc
public static void readXML(XmlDocument document)
{
if (document == null)
{
throw new ArgumentNullException("document");
}
XmlNode specificNode = document.SelectSingleNode("/Response/ResourceSets/ResourceSet/Resources/Location/BoundingBox");
if (specificNode != null)
{
XmlNodeReader specificNodeReader = new XmlNodeReader(specificNode);
while (specificNodeReader.Read())
{
Console.WriteLine(specificNodeReader.Value);
}
}
}
The xml looks like this:
<?xml version="1.0" encoding="utf-8" ?>
- <Response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/search/local/ws/rest/v1">
<Copyright>Copyright © 2012 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.</Copyright>
<BrandLogoUri>http://dev.virtualearth.net/Branding/logo_powered_by.png</BrandLogoUri>
<StatusCode>200</StatusCode>
<StatusDescription>OK</StatusDescription>
<AuthenticationResultCode>ValidCredentials</AuthenticationResultCode>
<TraceId>f651e16fe1204e12b848084d73f5148d|SINM001008|02.00.83.1900|SINMSNVM001115, SINMSNVM001124</TraceId>
- <ResourceSets>
- <ResourceSet>
<EstimatedTotal>1</EstimatedTotal>
- <Resources>
- <Location>
<Name><Some Name</Name>
- <Point>
<Latitude>47.640570402145386</Latitude>
<Longitude>-122.12937377393246</Longitude>
</Point>
- <BoundingBox>
<SouthLatitude>47.636707684574709</SouthLatitude>
<WestLongitude>-122.13701709146854</WestLongitude>
<NorthLatitude>47.644433119716062</NorthLatitude>
<EastLongitude>-122.12173045639638</EastLongitude>
</BoundingBox>
<EntityType>Address</EntityType>
</Location>
</Resources>
</ResourceSet>
</ResourceSets>
</Response>
Can someone point out, what I am missing here?
Because your actual xml has a namespace, you will need to include it in any Xpath queries you use. Since you already have the xml loaded in an XmlDocument, you don't need an XmlReader
XmlNamespaceManager nsm = new XmlNamespaceManager(document.NameTable);
nsm.AddNamespace("ms", "http://schemas.microsoft.com/search/local/ws/rest/v1");
XmlNode boundingBoxNode = document.SelectSingleNode("/ms:Response/ms:ResourceSets/ms:ResourceSet/ms:Resources/ms:Location/ms:BoundingBox", nsm);
if (boundingBoxNode != null)
{
Console.WriteLine(boundingBoxNode.SelectSingleNode("ms:SouthLatitude", nsm).InnerText);
Console.WriteLine(boundingBoxNode.SelectSingleNode("ms:NorthLatitude", nsm).InnerText);
Console.WriteLine(boundingBoxNode.SelectSingleNode("ms:EastLongitude", nsm).InnerText);
Console.WriteLine(boundingBoxNode.SelectSingleNode("ms:WestLongitude", nsm).InnerText);
}
You can also do this in Linq to Xml:
XNamespace ns = "http://schemas.microsoft.com/search/local/ws/rest/v1";
var boundingBox = document
.Descendants(ns + "Response")
.Descendants(ns + "ResourceSets")
.Descendants(ns + "ResourceSet")
.Descendants(ns + "Resources")
.Descendants(ns + "Location")
.Descendants(ns + "BoundingBox");
if (boundingBox != null)
{
Console.WriteLine(boundingBox.Descendants(ns + "SouthLatitude").First().Value);
Console.WriteLine(boundingBox.Descendants(ns + "NorthLatitude").First().Value);
Console.WriteLine(boundingBox.Descendants(ns + "EastLongitude").First().Value);
Console.WriteLine(boundingBox.Descendants(ns + "WestLongitude").First().Value);
}
XmlNode specificNode = document.SelectSingleNode("/Response/ResourceSets/ResourceSet/Resources/Location/BoundingBox");
if (specificNode != null)
{
foreach (XmlNode child in specificNode.ChildNodes)
{
Console.WriteLine(child.InnerText);
}
}
Should do the trick. Of course a lot of credit goes to Henk Holterman in his earlier answer.
Related
i have an xml file that as shown below
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfEtiquette xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Etiquette>
<BgColor>#8075D1C5</BgColor>
<BorderColor>#FF4E5B6F</BorderColor>
<AssociatedAffaireId>
<string>d4689f33-5600-47fe-883d-efcbf5e469c2</string>
<string>203cc4a8-8c24-4a2d-837c-29c7c1f73007</string>
<string>1bae35dd-d501-4d87-bdd4-147fc0ba29d2</string>
</AssociatedAffaireId>
<Label>Ouverte</Label>
</Etiquette>
</ArrayOfEtiquette>
I need to delete only
<string>203cc4a8-8c24-4a2d-837c-29c7c1f73007</string>
this is the code i tried, but its not working,
XDocument xmlSettings = XDocument.Load(chemin + "\\Etiquettes.xml");
if(xmlSettings.ToString().Contains(aff.Id))
{
string newXmlSettings = xmlSettings.ToString().Replace("<string>" +
aff.Id+ "</string>","");
}
xmlSettings.Save(chemin + "\\Etiquettes.xml");
Regards.
You can try with LINQ
//load the xml
var xdoc = XDocument.Load(filePath);
//find and remove
xdoc.Descendants("string")
.Where(x => x.Value == "203cc4a8-8c24-4a2d-837c-29c7c1f73007")
.Remove();
//save it back
xdoc.Save(filePath);
I'm in a situation where i need to get rid of my parentnode, but not my childnodes.
Here is how it loooks:
<?xml version="1.0" encoding="utf-8"?>
<ns0:MisMessage>
<mislife>
<party/>
<datetime>2018-06-04T09:35:33</datetime>
<insurance">
<number>123</number>
<amount>3</amount>
<indicator></indicator>
<text>asd</text>
</insurance>
</mislife>
<ns0:Message/>
</ns0:MisMessage>
And here is how i want it to look after i'm done.
<mislife>
<party/>
<datetime>2018-06-04T09:35:33</datetime>
<insurance">
<number>123</number>
<amount>3</amount>
<indicator></indicator>
<text>asd</text>
</insurance>
</mislife>
Is there any easy way to do this? I have tried and tried and tried. I have been looking all over the internet and i can't find out how to do it. The thing i want to remove will always be named ns0: in the beggning. Can i do it by removeing with substrings? THANKS!
I solved it like below, i converted the XMLDocument to XDocument and then used the descendants. Just like #bommelding showed in his example. Thank you all!
var xDocument = ToXDocument(xmlDocument);
if (xDocument != null)
{
var mislife = xDocument.Descendants("mislife").FirstOrDefault();
if (mislife != null)
{
return mislife;
}
}
public static XDocument ToXDocument(XmlDocument xmlDocument)
{
using (var nodeReader = new XmlNodeReader(xmlDocument))
{
nodeReader.MoveToContent();
return XDocument.Load(nodeReader);
}
}
XDocument doc = XDocument.Load(fileName);
XElement data = doc
.Descendants("mislife") // find your target
.Single(); // be brave, there should be exactly 1
data.Save(otherFileName); // saves with document <? ... ?>
Simple way with Linq (remember to add using System.Xml.Linq;):
string testxml = #"
<?xml version=""1.0"" encoding=""UTF-8""?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>";
XDocument doc = XDocument.Parse(testxml).Descendants().First().Document;
doc will be your xml without the root element
XDocument can load from files with
XDocument.Load("path");
or read XML like I did with
Xml.Parse("<xml....>");
and have also other options.
Result is:
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
I have this XML
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Header>
<wss:Security xmlns:wss="http://schemas.xmlsoap.org/ws/2002/12/secext">
<wss:UsernameToken>
<wss:Username>username</wss:Username>
<wss:Password>password</wss:Password>
<wss:Nonce></wss:Nonce>
<wss:Created></wss:Created>
</wss:UsernameToken>
</wss:Security>
</S:Header>
<S:Body>
<TaxRegistrationNumber>213213123</TaxRegistrationNumber>
<CompanyName>sadsadasd</CompanyName>
</S:Body>
</S:Envelope>
I want to accesses to the value of <wss:Username> and set a value in <wss:Nonce> node.
I already try 3 ways to get value of <wss:Username> on C# project:
First:
XDocument xmlFile = XDocument.Load(xmlpathfile);
XmlNamespaceManager ns = new XmlNamespaceManager(new NameTable());
ns.AddNamespace("wss", "http://schemas.xmlsoap.org/ws/2002/12/secext/");
XElement UserFinanc = xmlFile.XPathSelectElement("wss:Security/wss:UsernameToken/wss:Username", ns);
Second:
XDocument xmlFile = XDocument.Load(xmlpathfile);
XmlNamespaceManager ns = new XmlNamespaceManager(new NameTable());
var element = xmlFile.Descendants(wss + "Security").Descendants(wss + "UsernameToken").Where(x => x.Descendants(wss + "Username").Any(y => y.Value != "")).First().Element(wss + "UsernameToken");
if (element != null)
MessageBox.Show(element.Element(wss + "Username").Value).Value);
Third:
string grandChild = (string) (from el in xmlFile.Descendants(wss + "Username") select el).First();
MsgBox.Show(grandChild);
I always have similar errors like 'The sequence contains no elements'
Your first attempt is almost right. There are a couple things missing:
The namespace defined in code must be an exact match to the one in the xml. In your case the namespace in code has an extra trailing slash. It should be http://schemas.xmlsoap.org/ws/2002/12/secext.
The XPath expression should be //wss:Security/wss:UsernameToken/wss:Username. The leading slashes basically mean "look for this node anywhere". Alternatively, you could write out the whole path begining with <S:Envelope>. You would need to add the soap envelope namespace to your code as well.
I am attempting to get all the Pit XML elements from a Drainage_String XML node.
My Problem: When I go to retrieve all the Pit elements from the node, the XMLNodeList is always empty. I know that the node does contain 2 Pit elements so it should contain 2 node elements.
What is going wrong?
XmlDocument xdoc = new XmlDocument();
xdoc.Load(xmlFilePath);
XmlNodeList xNodes = xdoc.DocumentElement.GetElementsByTagName("string_drainage");
foreach (XmlNode dStr in xNodes) {
XmlNodeList pits = dStr.SelectNodes("pit");
MessageBox.Show("Num: "+pits.Count.ToString(), "Number");
// always outputs "Num: 0"
}
Example data I am using:
<string_drainage>
<pit>
<name>MH. </name>
<ip>0</ip>
<ratio>0</ratio>
<x>212908.89268569</x>
<y>612015.26122586</y>
<z>80.62414621</z>
</pit>
</string_drainage>
Detailed data:
<?xml version="1.0"?>
<xml12d xmlns="http://www.12d.com/schema/xml12d-10.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" language="English" version="1.0" date="2013-08-27" time="16:33:14" xsi:schemaLocation="http://www.12d.com/schema/xml12d-10.0 http://www.12d.com/schema/xml12d-10.0/xml12d.xsd">
<meta_data>
<units>
<metric>
<linear>metre</linear>
<area>square metre</area>
<volume>cubic metre</volume>
<temperature>celsius</temperature>
<pressure>millibars</pressure>
<angular>decimal degrees</angular>
<direction>decimal degrees</direction>
</metric>
</units>
<application>
<name>12d Model</name>
<manufacturer>12d Solutions Pty Ltd</manufacturer>
<manufacturer_url>www.12d.com</manufacturer_url>
<application>12d Model 10.0C1j</application>
<application_build>10.1.10.22</application_build>
<application_path>C:\Program Files\12d\12dmodel\10.00\nt.x64\12d.exe</application_path>
<application_date_gmt>24-Jul-2013 02:18:30</application_date_gmt>
<application_date>24-Jul-2013 12:18:30</application_date>
<project_name>mjkhjk</project_name>
<project_guid>{30A05217-706A-41c1-AF53-0D1A0975A5D0}</project_guid>
<project_folder>C:\12djobs\mjkhjk</project_folder>
<client>12d Training - NSW</client>
<dongle>572d471062</dongle>
<environment/>
<env4d>C:\12d\10.00\user\env.4d</env4d>
<user>Sam Zielke-Ryner</user>
<export_file_name>Tttt.xml</export_file_name>
<export_date_gmt>27-Aug-2013 06:33:14</export_date_gmt>
<export_date>27-Aug-2013 16:33:14</export_date>
</application>
</meta_data>
<comments>
<manufacturer>12d Solutions Pty Ltd</manufacturer>
<manufacturer_url>www.12d.com</manufacturer_url>
<application>12d Model 10.0C1j</application>
<application_build>10.1.10.22</application_build>
<application_path>C:\Program Files\12d\12dmodel\10.00\nt.x64\12d.exe</application_path>
<application_date_gmt>24-Jul-2013 02:18:30</application_date_gmt>
<application_date>24-Jul-2013 12:18:30</application_date>
<export_file_name>Tttt.xml</export_file_name>
<export_date_gmt>27-Aug-2013 06:33:14</export_date_gmt>
<export_date>27-Aug-2013 16:33:14</export_date>
</comments>
<string_drainage>
<name/>
<time_created>29-Jul-2013 02:02:03</time_created>
<time_updated>29-Jul-2013 02:02:11</time_updated>
<outfall>null</outfall>
<flow_direction>1</flow_direction>
<use_pit_con_points>false</use_pit_con_points>
<data_3d>
<p>212908.89268569 612015.26122586 0</p>
<p>212715.09268598 612007.24091243 84.20896044</p>
</data_3d>
<pit>
<name>MH. </name>
<type>CONC COVER</type>
<road_name/>
<road_chainage>null</road_chainage>
<diameter>1.1</diameter>
<con_point_mode>Points</con_point_mode>
<floating>true</floating>
<hgl>null</hgl>
<chainage>0</chainage>
<ip>0</ip>
<ratio>0</ratio>
<x>212908.89268569</x>
<y>612015.26122586</y>
<z>80.62414621</z>
</pit>
<pit>
<name>MH. </name>
<type>CONC COVER</type>
<road_name/>
<road_chainage>null</road_chainage>
<diameter>1.1</diameter>
<con_point_mode>Points</con_point_mode>
<floating>true</floating>
<hgl>null</hgl>
<chainage>193.96588699</chainage>
<ip>1</ip>
<ratio>0</ratio>
<x>212715.09268598</x>
<y>612007.24091243</y>
<z>84.20896044</z>
</pit>
<pipe>
<name>A</name>
<type>PVC</type>
<diameter>0.15</diameter>
<nominal_diameter>0.15</nominal_diameter>
<us_level>77.38411559</us_level>
<ds_level>79.32377446</ds_level>
<us_hgl>0</us_hgl>
<ds_hgl>0</ds_hgl>
<flow_velocity>0</flow_velocity>
<flow_volume>0</flow_volume>
<attributes>
<real>
<name>nominal diameter</name>
<value>0.15</value>
</real>
<real>
<name>calculated critical cover chainage</name>
<value>4.31482574</value>
</real>
</attributes>
</pipe>
</string_drainage>
</xml12d>
The call to SelectNodes requires the default namespace to be added to it.
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdoc.NameTable);
nsmgr.AddNamespace("x", xdoc.DocumentElement.NamespaceURI);
XmlNodeList pits = dStr.SelectNodes("x:pit");
Refer to the help located here
A tip I use for xml files is to always have namespaces aliased in xml files I use. Otherwise its harder to write xpath references to them.
I hope this will help you
test.xml is a copy/paste of your xml
static void Main(string[] args)
{
XmlDocument xdoc = new XmlDocument();
xdoc.Load(#"c:\test.xml");
XmlNodeList xNodes = xdoc.DocumentElement.SelectNodes("pit");
Console.WriteLine("Num: " + xNodes.Count.ToString());
foreach (XmlNode dStr in xNodes)
{
Console.WriteLine("Name: " + dStr.SelectSingleNode("name").InnerText);
Console.WriteLine("ip: " + dStr.SelectSingleNode("ip").InnerText);
Console.WriteLine("ratio: " + dStr.SelectSingleNode("ratio").InnerText);
Console.WriteLine("X: " + dStr.SelectSingleNode("z").InnerText);
Console.WriteLine("Y: " + dStr.SelectSingleNode("y").InnerText);
Console.WriteLine("X: " + dStr.SelectSingleNode("x").InnerText);
}
Console.Read();
}
maybe is better use XmlNode and XmlSingleNode of Xmldocument
I am coding for WP7. I am expecting this code below to read the XML below:
_xml = XElement.Parse(e.Result);
results.Items.Clear();
foreach (XElement value in _xml
.Descendants("ResourceSets").Descendants("ResourceSet")
.Descendants("Resources").Descendants("Location"))
{
Results _item = new Results();
_item.Place = value.Element("Name").Value;
_item.Lat = value.Element("Point").Element("Latitude").Value;
_item.Long = value.Element("Point").Element("Longitude").Value;
results.Items.Add(_item);
}
But the foreach loop wont read it and place it in the _items.
<?xml version="1.0" encoding="utf-8" ?>
<Response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/search/local/ws/rest/v1">
<Copyright>Copyright © 2011 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.</Copyright>
<BrandLogoUri>http://dev.virtualearth.net/Branding/logo_powered_by.png</BrandLogoUri>
<StatusCode>200</StatusCode>
<StatusDescription>OK</StatusDescription>
<AuthenticationResultCode>ValidCredentials</AuthenticationResultCode>
<TraceId>703e7f1427dd425185ded546ba8a0d2c|LTSM001154|02.00.126.3000|LTSMSNVM002008, LTSMSNVM001854, LTSMSNVM001853</TraceId>
<ResourceSets>
<ResourceSet>
<EstimatedTotal>4</EstimatedTotal>
<Resources>
<Location>
<Name>Ashford, Kent, United Kingdom</Name>
<Point>
<Latitude>51.146636679768562</Latitude>
<Longitude>0.87603025138378143</Longitude>
</Point>
<BoundingBox>
<SouthLatitude>51.076602190732956</SouthLatitude>
<WestLongitude>0.72853825986385345</WestLongitude>
<NorthLatitude>51.21656522154808</NorthLatitude>
<EastLongitude>1.0235222429037094</EastLongitude>
</BoundingBox>
<EntityType>PopulatedPlace</EntityType>
<Address>
<AdminDistrict>England</AdminDistrict>
<AdminDistrict2>Kent</AdminDistrict2>
<CountryRegion>United Kingdom</CountryRegion>
<FormattedAddress>Ashford, Kent, United Kingdom</FormattedAddress>
<Locality>Ashford</Locality>
</Address>
<Confidence>High</Confidence>
</Location>
</Resources>
</ResourceSet>
</ResourceSets>
</Response>
It looks like you're missing the namespace on each of your element names. Try this:
XNamespace xns = "http://schemas.microsoft.com/search/local/ws/rest/v1";
_xml = XElement.Parse(e.Result);
results.Items.Clear();
foreach (XElement value in _xml
.Descendants(xns + "ResourceSets").Descendants(xns + "ResourceSet")
.Descendants(xns + "Resources").Descendants(xns + "Location"))
{
Results _item = new Results();
_item.Place = value.Element(xns + "Name").Value;
_item.Lat = value.Element(xns + "Point").Element(xns + "Latitude").Value;
_item.Long = value.Element(xns + "Point").Element(xns + "Longitude").Value;
results.Items.Add(_item);
}
Is there a particular reason why you're using Descendants?
You could just do:
XmlDocument doc = new XmlDocument();
doc.Load(YourXMLPath);
XmlNode locationNode = doc["ResourceSets"]["ResourceSet"]["Resources"]["Location"];
foreach(XmlElement value in locationNode.Children)
{
Results _item = new Results();
_item.Place = value.Element("Name").Value;
_item.Lat = value.Element("Point").Element("Latitude").Value;
_item.Long = value.Element("Point").Element("Longitude").Value;
results.Items.Add(_item);
}
I don't have VS right now, but that should be close to it.
Of course a good behavior would be to check if nodes are null before getting the next one.
public ObservableCollection<Results> result = new ObservableCollection<Results>();
XDocument xmldoc = XDocument.Parse(e.Result.ToString());
var data = from c in xmldoc.Descendants("ResourceSets").Descendants("ResourceSet").Descendants("Resources").Descendants("Location")
select new Results{
Place = c.Element("Name").Value;
Lat = c.Element("Point").Element("Latitude").Value;
Long = c.Element("Point").Element("Longitude").Value;
};
foreach (Results obj in data)
{
result.Add(obj);
}
Have not tried, but this is how I do it.