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.
Related
<GetPromotionByIdResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" MajorVersion="2" xmlns="http://fake.com/services">
<Header>
<Response ResponseCode="OK">
<RequestID>1</RequestID>
</Response>
</Header>
<Promotion PromotionId="5200" EffectiveDate="2014-10-10T00:00:00" ExpirationDate="2014-11-16T23:59:00" PromotionStatus="Active" PromotionTypeName="DefaultPromotion">
<Description TypeCode="Long" Culture="en-AU">Promotion Description</Description>
</Promotion>
</GetPromotionByIdResponse>
Im trying to extract this
<Promotion PromotionId="5200" EffectiveDate="2014-10-10T00:00:00" ExpirationDate="2014-11-16T23:59:00" PromotionStatus="Active" PromotionTypeName="DefaultPromotion">
<Description TypeCode="Long" Culture="en-AU">Promotion Description</Description>
</Promotion>
and convert the PromotionId="5200" to PromotionId="XXX"
I can extract the < Promotion > element with the below code but cant work out how to change the attribute
XNamespace xmlResponseNamespace = xmlPromotionResponse.Root.GetDefaultNamespace();
XmlNamespaceManager nsm = new XmlNamespaceManager(new NameTable());
nsm.AddNamespace("def", xmlResponseNamespace.ToString());
XElement xmlPromotionElement =
xmlPromotionResponse
.Descendants().SingleOrDefault(p => p.Name.LocalName == "Promotion");
You can try this way :
XNamespace ns = "http://fake.com/services";
XElement xmlPromotionElement = xmlPromotionResponse.Descendants(ns+"Promotion")
.SingleOrDefault();
xmlPromotionElement.Attribute("PromotionId").Value = "XXX";
Use simple XNamespace + local-name to reference an element in namespace. Then you can use .Attribute() method to get XAttribute from an XElement and change the attribute's value.
Try this : It returns the value of all attributes in Promotion Tag.
XNamespace ns1 = XNamespace.Get("http://fake.com/services");
var readPromotion = from a in xx.Descendants(ns1 + "Promotion")
select new
{
PromotionID = (string)a.Attribute("PromotionId"),
EffectiveDate = (string)a.Attribute("EffectiveDate"),
ExpirationDate = (string)a.Attribute("ExpirationDate"),
PromotionStatus = (string)a.Attribute("PromotionStatus"),
PromotionTypeName = (string)a.Attribute("PromotionTypeName"),
Description = (string)a.Value
};
foreach (var read in readPromotion)
{
// Read values
}
I have xml:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<UpdateMemberHireStatus xmlns="http://tempuri.org/">
<member>
<HireAvailability>
<code>1</code>
<name>פנוי</name>
</HireAvailability>
<HireRejectReason>
<code>2</code>
<name>wow</name>
</HireRejectReason>
<IdNumber>43504349</IdNumber>
<note> </note>
</member>
</UpdateMemberHireStatus>
and I want to use LINQ to access all the nodes in the xml.
Here's what I have tried:
XNamespace ns = "tempuri.org/";
IEnumerable<HireStatus> status = from r in doc.Descendants(ns + "UpdateMemberHireStatus")
.Descendants(ns + "member")
select new HireStatus() { };
return status.ToList();
Use Descendants
var xml = XDocument.Load(XMLStream);
var allEle = xml.Descendants("UpdateMemberHireStatus"); //you can do linq now.
You can use XDocument also in the following way:
string xmlPath = "D://member.xml";
XmlDocument doc = new XmlDocument();
xdoc = XDocument.Load(xmlPath);
doc.LoadXml(xdoc.ToString());
var memberStatus= (from mem in xdoc.Descendants("member")
select mem);
foreach (XElement element in memberStatuses.ToList())
IEnumerable<XNode> nodes = element.Nodes();
var x = XElement.Load(XMLStream);
var all = x.DescendantNodes();
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.
I'm trying to import the kml xml Google earth file into an application, but i can't seem to get the xDocument syntax right in order to do what i want, i'm wondering if anyone could suggest a way to read in the kml xml file.
I understand the basics of xml import but can't get anything working with xDocument and Linq, ideally i'd like to get each Placemark as an object and add them to my Entity Framework driven db. Any suggestions as to how i should do this would be great, as i'm just starting out with Linq and could do with some pointers. The xml is laid out as below
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
<Document>
<Placemark>
<name>XXX</name>
<description>XXX</description>
<styleUrl>XXX</styleUrl>
<Point>
<coordinates>XXX</coordinates>
</Point>
</Placemark>
<Placemark>
<name>XXX</name>
<description>XXX</description>
<styleUrl>XXX</styleUrl>
<Point>
<coordinates>XXX</coordinates>
</Point>
</Placemark>
</Document>
</kml>
You didn't include any code, but I would guess that you forgot to include your namespace when referencing things. Here is an example.
Basic access:
var placemarks = xdoc.Element("kml").Element("Document").Elements("Placemark");
Using namespaces:
var ns = XNamespace.Get("http://earth.google.com/kml/2.2");
var placemarks = xdoc.Element(ns + "kml").Element(ns + "Document").Elements(ns + "Placemark");
My guess is that you've forgotten to use the namespace in your LINQ to XML queries. It's easy enough to extract the data from this:
XNamespace ns = "http://earth.google.com/kml/2.2";
var doc = XDocument.Load("file.xml");
var query = doc.Root
.Element(ns + "Document")
.Elements(ns + "Placemark")
.Select(x => new PlaceMark // I assume you've already got this
{
Name = x.Element(ns + "name").Value,
Description = x.Element(ns + "description").Value,
// etc
});
If that doesn't help, please post a complete example of what you've tried, and what went wrong.
I used SharmpKml and its documentation to extract information from KML file.
using SharpKml.Dom;
using SharpKml.Engine;
using SharpKml.Dom.GX;
TextReader reader = File.OpenText(filePath);
KmlFile file = KmlFile.Load(reader);
_kml = file.Root as Kml;
sPlaceMarks[] tempPlaceMarks = new sPlaceMarks[1000];
if (_kml != null)
{
foreach (var placemark in _kml.Flatten().OfType<Placemark>())
{
tempPlaceMarks[numOfPlaceMarks].Name = placemark.Name;
tempPlaceMarks[numOfPlaceMarks].Description = placemark.Description.Text;
tempPlaceMarks[numOfPlaceMarks].StyleUrl = placemark.StyleUrl;
tempPlaceMarks[numOfPlaceMarks].point = placemark.Geometry as SharpKml.Dom.Point;
tempPlaceMarks[numOfPlaceMarks].CoordinateX = tempPlaceMarks[numOfPlaceMarks].point.Coordinate.Longitude;
tempPlaceMarks[numOfPlaceMarks].CoordinateY = tempPlaceMarks[numOfPlaceMarks].point.Coordinate.Latitude;
tempPlaceMarks[numOfPlaceMarks].CoordinateZ = tempPlaceMarks[numOfPlaceMarks].point.Coordinate.Altitude;
numOfPlaceMarks++;
}
foreach (var lookAt in _kml.Flatten().OfType<LookAt>())
{
Placemark placemark = (Placemark)lookAt.Parent;
for (int i = 0; i < numOfPlaceMarks; i++)
{
if (placemark.Name == tempPlaceMarks[i].Name)
{
tempPlaceMarks[i].Name = placemark.Name;
tempPlaceMarks[i].Description = placemark.Description.Text;
tempPlaceMarks[i].StyleUrl = placemark.StyleUrl;
tempPlaceMarks[i].altitude = lookAt.Altitude;
tempPlaceMarks[i].AltitudeMode =(SharpKml.Dom.GX.AltitudeMode)lookAt.GXAltitudeMode;
tempPlaceMarks[i].Heading = lookAt.Heading;
tempPlaceMarks[i].Latitude = lookAt.Latitude;
tempPlaceMarks[i].Longitude = lookAt.Longitude;
tempPlaceMarks[i].Range = lookAt.Range;
tempPlaceMarks[i].Tilt = lookAt.Tilt;
break;
}
}
}
var xDoc = XDocument.Load("a.xml");
XNamespace ns = "http://earth.google.com/kml/2.2";
var placemarks = xDoc.Descendants(ns+"Placemark")
.Select(p => new
{
Name = p.Element(ns+"name").Value,
Desc = p.Element(ns+"description").Value
})
.ToList();
Your kml file must contains
<kml xmlns="http://www.opengis.net/kml/2.2" ...
instead of
<kml xmlns="http://earth.google.com/kml/2.2"> ...
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Report SYSTEM "https://abc.mycompany.com/abc/processingreports/processeddtd/abcd_1_8.dtd">
<Report Name="Daily TRANSACTIONS"
Version="1.8"
xmlns="https://abc.mycompany.com/abc/processingreports/processeddtd/abcd_1_8.dtd"
OrgID="ABC_PQR" StartDate="2011-03-10T00:00:00+00:00" EndDate="2011-03-11T00:00:00+00:00">
<Requests>
<Request ID="2"
Date="2011-03-10T00:21:14+00:00"
OrderNumber="1">
<BillTo>
<FirstName />
</BillTo>
<LineItems>
<LineItem Number="0">
<Quantity />
</LineItem>
</LineItems>
</Request>
<Request ID="2"
Date="2011-03-10T00:21:14+00:00"
OrderNumber="1">
TransactionNumber="389958330911111">
<BillTo>
<FirstName>A</FirstName>
</BillTo>
<LineItems>
<LineItem Number="0">
<Quantity>1</Quantity>
</LineItem>
</LineItems>
<UniqueData>
<UniqueNumber>11111111111111111111111111111</UniqueNumber>
</UniqueData></Request></Requests></Report>
In above XML file using Linq i just
want to extract OrderNumber and
UniqueNumber
OrderNumber="1"
11111111111111111111111111111
Any ideas, suggestions to extract these details?
I can select elements from above xml file but UniqueNumber is not associated with OrderNumber
I am looking for something below (ignore lines where UniqueNumber is not present)
OrderNumber - assosicated UniqueNumber
Update
In "requiredElements" i am expecting two coulmns OrderNumber and UniqueNumber and holding associated values with each other as 1 and 11111 and so one
#region FileOpen with UTF8 Encoding
TextReader sr = new StreamReader(cFileName, Encoding.UTF8);
XDocument reportfile = XDocument.Load(sr, LoadOptions.SetBaseUri);
XElement xd = XElement.Parse(reportfile.ToString());
sr.Close();
#endregion
XNamespace ns = xd.Attribute("xmlns").Value;
var requiredElements = (from resultquery in reportfile.Descendants()
select new
{
OrderNumber = resultquery.Attribute("OrderNumber"),
UniqueNumber= (string)resultquery.Element(AddNameSpace(ns, "UniqueNumber")),
}
);
Here is some sample:
XDocument doc = XDocument.Load(#"file.xml");
XNamespace df = doc.Root.Name.Namespace;
var results = from request in doc.Descendants(df + "Request")
where request.Elements(df + "UniqueData").Elements(df + "UniqueNumber").Any()
select new
{
ordNumber = (int)request.Attribute("OrderNumber"),
uniqueNumber = (decimal)request.Element(df + "UniqueData").Element(df + "UniqueNumber")
};
foreach (var result in results)
{
Console.WriteLine("{0}-{1}", result.ordNumber, result.uniqueNumber);
}