I have this XML:
<palinsesto>
<giorno label="Mer" data="2014/12/31">
<canale description="Premium Cinema" id="KE">
<prg Pod="N" Nettv="N" orafine="06:30" orainizio="06:00" replica="No" primaTv="No">
<durata duratapixel="30">30</durata>
<tipologia>Type</tipologia>
<titolo>evento iniziato ieri</titolo>
<descrizione>--</descrizione>
<audio sottotitoli="No subtitles" audioType="Mono" doppioAudio="One language">Not used</audio>
<parentalRating>LIBERO DA DIVIETI</parentalRating>
<trafficLight/>
<anno>--</anno>
<paese>--</paese>
and i need to read the value in prg class and palinsesto class, i try in this mode but not work
XDocument doc = XDocument.Parse(e.Result);
var canal = doc.Descendants(XName.Get("description", "canale")).FirstOrDefault();
var date = doc.Descendants(XName.Get("data", "giorno")).FirstOrDefault();
var title = doc.Descendants(XName.Get("titolo", "prg")).FirstOrDefault();
return always error
It looks like you've misunderstood names, attributes and elements. It looks like you just want something like:
XDocument doc = XDocument.Parse(e.Result);
var root = doc.Root;
var canal = root.Element("canale").Attribute("description").Value;
var date = root.Element("giorno").Attribute("data").Value;
var title = root.Element("titolo").Value;
However:
Currently none of your first three elements are closed, which would cause the above to fail; it's not clear what your real XML would look like. You should indent it to show the intended structure.
Your date is not represented in the normal way for XML - if you're in control of the XML, it would be better to have a value of 2014-12-31
The above code assumes you just want the first element from the root. If that's not the case, you'll need to give us more information
You do not require this XName overload here - the second parameter is used to provide a namespace, which isn't present in the xml you've provided. I believe you are confusing attributes and xmlns namespaces. In order to obtain the attributes, use .Attributes(), as follows:
var canal = doc.Descendants("canale").Attributes("description").FirstOrDefault();
var date = doc.Descendants("giorno").Attributes("data").FirstOrDefault();
var title = doc.Descendants("prg").Attributes("titolo").FirstOrDefault();
Related
I am building an XDocument and I have unit tests to test the output. One of the things I want to test for is that invalid strings are being formatted for XML properly. I have discovered that calling .ToString() on the XDoc itself properly formats the invalid strings for XML. However, in my testing I am retrieving specific Elements or Attributes off of the XDoc and testing the values. This does not format the values for XML. How do I go about getting these values in their escaped format?
Answer: (thx Ed Plunkett)
myXDoc.Descendants("element2").First().FirstNode.ToString();
// result "Pork&Beans"
Sample:
var xml =
"<element1>" +
"<element2>Pork&Beans</element2>" +
"</element1>";
var myXDoc = XDocument.Load(xml);
var xDocString = myXDoc.ToString();
// result is formatted - <element1> <element2>Pork&Beans</element2> </element1>
var element2Value = myXDoc.Decendents("element2").First().Value;
// result is unformatted - Pork&Beans
Got it: Text elements in XML are nodes too.
var el2XML = myXDoc.Descendants("element2").First();
var porkAndAmpSemicolonBeans = el2XML.FirstNode.ToString();
You'll want to also check el2XML.Nodes.Count to make sure there's exactly one child in there.
System.Xml.XmlDocument is another option, because XmlNode has an InnerXml property that'll give you what you want:
var morePorkAndBeans = doc.SelectSingleNode("//element2").InnerXml;
I cant get my Xpath query to work though on paper it should be right. I even tried to get a single node without the attribute and could not even get this ...
What am I doing wrong ?
var trxXml = new XmlDocument();
trxXml.Load(InputTrxFile);
XmlElement root = trxXml.DocumentElement;
var unitTestResult = trxXml.GetElementsByTagName("UnitTestResult");
foreach (XmlElement runinfo in unitTestResult)
{
// Find failed tests, works fine then...
string TestName = runinfo.GetAttribute("testName"); // works fine
// Want to find equivalent TestDefinitions/UnitTest
/* Tried
TestRun/TestDefinitions/UnitTest[#name='thetest']
/TestRun/TestDefinitions/UnitTest[#name='thetest']
TestDefinitions/UnitTest[#name='thetest']
/TestDefinitions/UnitTest[#name='thetest']
UnitTest[#name='thetest']
variations with no attribute test JUST to get a node
Example http://www.csharp-examples.net/xml-nodes-by-attribute-value/
*/
var xpath = string.Format(#"/TestRun/TestDefinitions/UnitTest[#name='{0}']", TestName);
XmlNode node = trxXml.SelectSingleNode(xpath);
XmlNode node2 = root.SelectSingleNode(xpath);
// These all return null
Any query that begins with a / represents an absolute path, i.e. it is from the root of the document. It seems your UnitTestResult element (at the very least) encloses your TestRun elements.
To have your query take into account the current context, you need to reference the current context. This can be selected using ..
Secondly, your XML elements all have a namespace, and this needs to make up part of your query. A prefix needs to be added to a namespace manager, used in your query and the manager passed into the query method.
So, taking these together, define the prefix:
var manager = new XmlNamespaceManager(new NameTable());
manager.AddNamespace("t", "http://microsoft.com/schemas/VisualStudio/TeamTest/2010");
Change your query:
./t:TestRun/t:TestDefinitions/t:UnitTest[#name='{0}']
And pass the namespace manager to the method:
trxXml.SelectSingleNode(xpath, manager);
XPath and XmlDocument are pain, though. This would all be a lot more straightforward in LINQ to XML:
var doc = XDocument.Load(InputTrxFile);
var unitTestQuery =
from result in doc.Descendants(ns + "UnitTestResult")
let name = (string)result.Attribute("testName")
from unitTest in result.Descendants(ns + "UnitTest")
where (string)unitTest.Attribute("name") == name
select unitTest;
var unitTest = unitTestQuery.Single();
I'm currently using a loop which gives me a variable, which then needs to be fed into an Xpath method to get me any nodes with an attribute equal to my variable. So far, I've learned that Xpath allows you to select a node from the XML document using
root.SelectNodes("Element[#Attribute='SpecificValue']")
However, I'd like to know if there's a way I can insert a predefined variable where the specific value, so I can grab a different set of nodes with each iteration of my loop.
For example something like this:
string attribValue= "test"
root.SelectNodes("Element[#Attribute = attribValue]")
Use string formatting:
string attribValue = "test";
string expression = String.Format("Element[#Attribute = '{0}']", attribValue);
root.SelectNodes(expression);
Using XML Linq
XDocument doc = new XDocument();
XElement root = (XElement)doc.FirstNode;
string attribValue= "test";
var results = root.Descendants("Element").Where(x => x.Attribute("Attribute").Value == attribValue).ToList();
I try to get some data from Google Geocoding API with C# and ASP.net. But I have trouble with XML responce. I get valid XML and I can get evry element besides "address_component" element. (XML looks like this : http://maps.googleapis.com/...)
/* data is a string with XML from Google server */
XDocument receivedXml = new XDocument();
receivedXml = XDocument.Parse(data);
XName address = XName.Get("address_component");
var root = reciviedXml.Root; //returns corect XElement
XElement result = root.Element("result"); //returns corect XElement
IEnumerable<XElement> components = result.Elements("address_component"); //returns empty collection
This is another way, I'have tried it to with the same result.
var results = reciviedXml.Descendants("address_component");
And when I try to get some descendant of like:
var types = receivedXml.Descendants("type");
It's the empty collection to. But another elements in "result" tag (like the "location" tag)I can get successfully.
Thanks for any advice.
The following:
var receivedXml = XDocument.Load("http://maps.googleapis.com/maps/api/geocode/xml?latlng=49.1962253,16.6071422&sensor=false");
Console.WriteLine(receivedXml.Root.Element("result").Elements("address_component").Count());
Console.WriteLine(receivedXml.Descendants("address_component").Count());
Writes 10 and 28 respectively. Make sure you are using the same instance - in your question you usereceivedXml as well as reciviedXml so you may have two instances XDocument and one of these may contain different data. Also you don't need to instantiate XDocument as XDocument.Parse() will do it for you (and the address variable seems to be unused)
I'm trying to parse results from the YouTube API. I'm getting the results correctly as a string, but am unable to parse it correctly.
I followed suggestions on a previous thread, but am not getting any results.
My sample code is:
string response = youtubeService.GetSearchResults(search.Term, "published", 1, 50);
XDocument xDoc = XDocument.Parse(response, LoadOptions.SetLineInfo);
var list = xDoc.Descendants("entry").ToList();
var entries = from entry in xDoc.Descendants("entry")
select new
{
Id = entry.Element("id").Value,
Categories = entry.Elements("category").Select(c => c.Value)
//Published = entry.Element("published").Value,
//Title = entry.Element("title").Value,
//AuthorName = entry.Element("author").Element("name").Value,
//Thumnail = entry.Element("media:group").Elements("media:thumnail").ToList().ElementAt(0)
};
foreach (var entry in entries)
{
// entry.Id and entry.Categories available here
}
The problem is that entries has a count of 0 even though the XDocument clearly has the valid values.
The value of the response variable (Sample XML) can be seen here: http://snipt.org/lWm
(FYI: The youTube schema is listed here: http://code.google.com/apis/youtube/2.0/developers_guide_protocol_understanding_video_feeds.html)
Can anyone tell me what I'm doing wrong here?
All the data is in the "http://www.w3.org/2005/Atom" namespace; you need to use this throughout:
XNamespace ns = XNamespace.Get("http://www.w3.org/2005/Atom");
...
from entry in xDoc.Descendants(ns + "entry")
select new
{
Id = entry.Element(ns + "id").Value,
Categories = entry.Elements(ns + "category").Select(c => c.Value)
...
};
etc (untested)
When you see prefix:name, it means that name is in the namespace whose prefix has been declared as prefix. If you look at the top of the document, you'll see an xmlns:media=something. The something is the namespace used for anything with the prefix media.
This means you need to create an XNamespace for each of the namespaces you need to reference:
XNamespace media = XNamespace.Get("http://search.yahoo.com/mrss/");
and then use media for the names in that namespace:
media + "group"
The namespaces in this document are:
xmlns="http://www.w3.org/2005/Atom"
xmlns:app="http://www.w3.org/2007/app"
xmlns:media="http://search.yahoo.com/mrss/"
xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/"
xmlns:gd="http://schemas.google.com/g/2005"
xmlns:gml="http://www.opengis.net/gml"
xmlns:yt="http://gdata.youtube.com/schemas/2007"
xmlns:georss="http://www.georss.org/georss"
You need to set the namespace.
Creating an XName in a Namespace
As with XML, an XName can be in a namespace, or it can be in no namespace.
For C#, the recommended approach for creating an XName in a namespace is to declare the XNamespace object, then use the override of the addition operator.
http://msdn.microsoft.com/en-us/library/system.xml.linq.xname.aspx