I need to get the CountryName from this XML: http://api.hostip.info/?ip=12.215.42.19
The response XML is:
<HostipLookupResultSet version="1.0.1"
xmlns:gml="http://www.opengis.net/gml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.hostip.info/api/hostip-1.0.1.xsd">
<gml:description>This is the Hostip Lookup
Service</gml:description>
<gml:name>hostip</gml:name>
<gml:boundedBy>
<gml:Null>inapplicable</gml:Null>
</gml:boundedBy>
<gml:featureMember>
<Hostip>
<ip>12.215.42.19</ip>
<gml:name>Sugar Grove, IL</gml:name>
<countryName>UNITED STATES</countryName>
<countryAbbrev>US</countryAbbrev>
<!-- Co-ordinates are available as lng,lat -->
<ipLocation>
<gml:pointProperty>
<gml:Point srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
<gml:coordinates>-88.4588,41.7696</gml:coordinates>
</gml:Point>
</gml:pointProperty>
</ipLocation>
</Hostip>
</gml:featureMember>
</HostipLookupResultSet>
Problem is I can't include : in the Descendants method because it throws:
XmlException: The ':' chracater,
hexadecimal value 0x3A, cannot be
included in a name.
Thanks
try this
var descendants = from i in XDocument.Load(xml).Descendants("Hostip")
select i.Element("countryName");
Update
complete code for downloading the xml and finding the name of countryName
string xml;
using(var web = new WebClient())
{
xml = web.DownloadString("http://api.hostip.info/?ip=12.215.42.19");
}
var descendants = from i in XDocument.Parse(xml).Descendants("Hostip")
select i.Element("countryName");
A small example on how to apply namespaces in LINQ to XML:
XElement doc = XElement.Load("test.xml");
XNamespace ns = "http://www.opengis.net/gml";
var firstName = doc.Descendants(ns + "name").First().Value;
You need to reference the gml namespace; once you've done that you should be able to navigate using the tag names that appear to the right of "gml:"
UPDATE
I'm not sure what context you're applying this to, but here's a sample console app that works:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace LinqToXmlSample
{
class Program
{
static void Main(string[] args)
{
XElement x = XElement.Load("http://api.hostip.info/?ip=12.215.42.19");
foreach (XElement hostip in x.Descendants("Hostip"))
{
string country = Convert.ToString(hostip.Element("countryName").Value);
Console.WriteLine(country);
}
Console.ReadLine();
}
}
}
var gml = (XNamespace)"http://www.opengis.net/gml";
var doc = XDocument.Load(...) or XDocument.Parse(...);
var name = doc.Descendants(gml + "featureMember").Descendants("countryName").First().Value;
Or you could go brute force and strip all the namespaces:
void RemoveNamespace(XDocument xdoc)
{
foreach (XElement e in xdoc.Root.DescendantsAndSelf())
{
if (e.Name.Namespace != XNamespace.None)
{
e.Name = XNamespace.None.GetName(e.Name.LocalName);
}
if (e.Attributes().Any(a => a.IsNamespaceDeclaration || a.Name.Namespace != XNamespace.None))
{
e.ReplaceAttributes(e.Attributes().Select(a => a.IsNamespaceDeclaration ? null : a.Name.Namespace != XNamespace.None ? new XAttribute(XNamespace.None.GetName(a.Name.LocalName), a.Value) : a));
}
}
}
Related
I am trying to extract values of : url,ttype,tempTnxId,token,txnStage from the following XML string:
<?xml version="1.0" encoding="UTF-8"?>
<MMP>
<MERCHANT>
<RESPONSE>
<url>https://payment.xyz.com/paynetz/epi/fts</url>
<param name="ttype">abc</param>
<param name="tempTxnId">12319507</param>
<param name="token">x5H9RrhgfXvamaqEl6GpY4uCoXHN%2FlEm%2BUpaaKuMQus%3D</param>
<param name="txnStage">1</param>
</RESPONSE>
</MERCHANT>
</MMP>
So far I have only been able to extract values with index using following code:
foreach (XmlNode node in doc.SelectNodes("/MMP/MERCHANT/RESPONSE/param"))
{
string tempTxnId= doc.SelectNodes("/MMP/MERCHANT/RESPONSE/param")[1].InnerText;//only works with index and not name
}
/MMP/MERCHANT/RESPONSE/param or /MMP/MERCHANT/RESPONSE/ttype does not return anything.
This solution :Getting specified Node values from XML document
does not seem to be working for me.
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlstring);
var result = doc.Elements("table"); ///cant find Elements, Element is is not identified by the compiler
You commented that you cannot select by name ttype.
ttype is a value and not a name.
The element name is param.
The single attribute name of the element param is name.
If you need to get the InnerText of the element param with attribute name equal to ttype (or the other values) then you could do something like:
var xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><MMP><MERCHANT><RESPONSE><url>https://payment.xyz.com/paynetz/epi/fts</url><param name=\"ttype\">abc</param><param name=\"tempTxnId\">12319507</param><param name=\"token\">x5H9RrhgfXvamaqEl6GpY4uCoXHN%2FlEm%2BUpaaKuMQus%3D</param><param name=\"txnStage\">1</param></RESPONSE></MERCHANT></MMP>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
// This gets 4 nodes.
var paramNodes = doc.SelectNodes("/MMP/MERCHANT/RESPONSE/param");
foreach (XmlElement e in paramNodes)
{
Console.WriteLine(e.Attributes[0].Value + "=" + e.InnerText);
}
// These each get a single node.
var ttypeNode = doc.SelectSingleNode("/MMP/MERCHANT/RESPONSE/param[#name=\"ttype\"]");
var tempTxnIdNode = doc.SelectSingleNode("/MMP/MERCHANT/RESPONSE/param[#name=\"tempTxnId\"]");
var tokenNode = doc.SelectSingleNode("/MMP/MERCHANT/RESPONSE/param[#name=\"token\"]");
var txnStageNode = doc.SelectSingleNode("/MMP/MERCHANT/RESPONSE/param[#name=\"txnStage\"]");
Console.WriteLine(ttypeNode.InnerText);
Console.WriteLine(tempTxnIdNode.InnerText);
Console.WriteLine(tokenNode.InnerText);
Console.WriteLine(txnStageNode.InnerText);
You can select node by attribute value like this (assuming this is what you are trying to do):
doc.SelectNodes("/MMP/MERCHANT/RESPONSE/param[#name='ttype']")
.Cast<XmlNode>().ToList()
.ForEach(x=>Console.WriteLine(x.InnerText));
Using xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var response = doc.Descendants("RESPONSE").Select(x => new {
url = (string)x.Element("url"),
ttype = x.Elements().Where(y => (string)y.Attribute("name") == "ttype").Select(z => (string)z).FirstOrDefault(),
tempTxnId = x.Elements().Where(y => (string)y.Attribute("name") == "tempTxnId").Select(z => (string)z).FirstOrDefault(),
token = x.Elements().Where(y => (string)y.Attribute("name") == "token").Select(z => (string)z).FirstOrDefault(),
txnStage = x.Elements().Where(y => (string)y.Attribute("name") == "txnStage").Select(z => (int)z).FirstOrDefault()
}).FirstOrDefault();
}
}
}
I'm trying to parse out information from a XCCDF output file but my Linq-to-Xml queries keep returning empty. Here are some of the ones I've tried to this point:
XElement xelement = XElement.Load(s);
IEnumerable<XElement> findings = xelement.Elements();
XNamespace ns = "http://checklists.nist.gov/xccdf/1.1";
var findingDetails = from f in findings.Descendants(ns + "Benchmark")
select new
{
title = f.Element("title").Value
};
foreach (var fd in findingDetails)
{
Console.WriteLine(fd.ToString());
}
I also tried:
var findingDetails = from f in findings.Descendants(ns + "Benchmark")
select f;
var findingDetails = from f in findings.Descendants("Benchmark")
select new
{
title = f.Element("title").Value
};
var findingDetails = from f in findings.Elements(ns + "Benchmark")
select new
{
title = f.Element("title").Value
};
var findingDetails = from f in findings.Elements(ns + "Benchmark")
select f;
Here is a condensed version of the xccdf.xml file. Based on this version how would I get the title "Red Hat..." (line 5) and the title "daemon umask" (line 19)? (I do understand that my examples above do not attempt to get this data, I had to break it down to just trying to get anything...
<?xml version="1.0" encoding="UTF-8"?>
<cdf:Benchmark style="SCAP_1.1" resolved="1" id="RHEL_6_STIG" xsi:schemaLocation="http://checklists.nist.gov/xccdf/1.1 http://nvd.nist.gov/schema/xccdf-1.1.4.xsd http://cpe.mitre.org/dictionary/2.0 http://scap.nist.gov/schema/cpe/2.2/cpe-dictionary_2.2.xsd" xmlns:cdf="http://checklists.nist.gov/xccdf/1.1" xmlns:cpe="http://cpe.mitre.org/dictionary/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xhtml="http://www.w3.org/1999/xhtml">
<cdf:status date="2016-04-22">accepted</cdf:status>
<cdf:title>Red Hat Enterprise Linux 6 Security Technical Implementation Guide</cdf:title>
<cdf:description>The Red Hat Enterprise Linux 6 Security Technical Implementation Guide (STIG) is published as a tool to improve the security of Department of Defense (DoD) information systems. Comments or proposed revisions to this document should be sent via e-mail to the following address: disa.stig_spt#mail.mil.</cdf:description>
<cdf:notice id="terms-of-use"></cdf:notice>
<cdf:reference href="http://iase.disa.mil">
<dc:publisher>DISA</dc:publisher>
<dc:source>STIG.DOD.MIL</dc:source>
</cdf:reference>
<cdf:plain-text id="release-info">Release: 11 Benchmark Date: 22 Apr 2016</cdf:plain-text>
<cdf:platform idref="cpe:/o:redhat:enterprise_linux:6"></cdf:platform>
<cdf:version>1</cdf:version>
<cdf:Profile id="MAC-1_Classified">
<cdf:title>I - Mission Critical Classified</cdf:title>
</cdf:Profile>
<cdf:Value id="var_umask_for_daemons">
<cdf:title>daemon umask</cdf:title>
<cdf:description>Enter umask for daemons</cdf:description>
<cdf:value>022</cdf:value>
<cdf:value selector="022">022</cdf:value>
<cdf:value selector="027">027</cdf:value>
</cdf:Value>
</cdf:Benchmark>
Both Benchmark and title have the namespace http://checklists.nist.gov/xccdf/1.1, so you need to use this if you're going to query for title.
Secondly, you parse using XElement.Parse, so the result is an element representing the Benchmark element. You then get its child elements (status to Value). Then you search for descendants of any of those called Benchmark - you're not going to find any, as Benchmark was where you started.
This should work:
var element = XElement.Load(s);
var findingDetails = new
{
title = (string)element.Element(ns + "title")
};
Alternatively, load as a document:
var doc = XDocument.Load(s);
var findingDetails =
from benchmark in doc.Descendants(ns + "Benchmark")
select new
{
title = (string)benchmark.Element(ns + "title")
};
Try following
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ProgrammingBasics
{
class Exercise
{
const string FILENAME = #"c:\temp\test.xml";
static void Main()
{
XDocument doc = XDocument.Load(FILENAME);
var results = doc.Descendants().Where(x => x.Name.LocalName == "Benchmark").Select(y => new
{
title = (string)y.Elements().Where(z => z.Name.LocalName == "title").FirstOrDefault()
}).FirstOrDefault();
}
}
}
List<string> list = new List<string>();
foreach (XPathNavigator node in nav.Select("configuration/company/work/worktime"))
{
string day = getAttribute(node, "day");
string time = getAttribute(node, "time");
string worktype = ?? // how to get worktype attribute valuefrom parent node
list.Add(day,time,worktype); // add to list
}
</configuration>
<company>
<work worktype="homeWork">
<worktime day="30" time="10:28"></worktime>
<worktime day="25" time="10:50"></worktime>
</work>
<work worktype="officeWork">
<worktime day="12" time="09:28"></worktime>
<worktime day="15" time="12:28"></worktime>
</work>
</company>
</configuration>
need output as :
list[0] = homeWork,30,10:28
list[1] = homeWork,25,10:50
list[2] = officeWork,12,09:28
list[3] = officeWork,15,12:28
I am trying to get the list from XML but failed to get output like given above (using xpath navigator, how can I access parent node to get worktype attribute, and other remaining inner node attribute?
I'd suggest using LINQ to XML over XPath, but if you must use XPathNavigator then you need to iterate each work element followed by each of its worktime child elements. This way you can use the worktype from the parent context:
foreach (XPathNavigator work in nav.Select("configuration/company/work"))
{
var workType = work.GetAttribute("worktype", string.Empty);
foreach (XPathNavigator worktime in work.Select("worktime"))
{
var day = worktime.GetAttribute("day", string.Empty);
var time = worktime.GetAttribute("time", string.Empty);
list.Add($"{workType}, {day}, {time}");
}
}
See this fiddle for a working demo.
Use a nested loop. Initially retrieve the work nodes with configuration/company/work. Retrieve the worktype attribute and store in a variable. Then loop through the child worktype nodes and add a string to the list for each one
Use Net Library enhanced xml (linq xml)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var results = doc.Descendants("work").Select(x => new {
worktype = (string)x.Attribute("worktype"),
worktime = x.Elements("worktime").Select(y => new {
day = (int)y.Attribute("day"),
time = (DateTime)y.Attribute("time")
}).ToList()
}).ToList();
}
}
}
My XML looks like this
<Location>
<AChau>
<ACity>
<EHouse/>
<FHouse/>
<GHouse/>
</ACity>
<BCity>
<HHouse/>
<IHouse/>
<JHouse/>
<KHouse/>
</BCity>
</AChau>
</Location>
I find a number of ways, I am here to find the closest answer
Get All node name in xml in silverlight
But it reads all the descendants, I need is from "Location" get "AChau"
From "Location/AChau" get "ACity" "BCity"
From "Location/AChau/ACity" get "EHouse" "FHouse" "GHouse"
How can I read only child node?
Assuming that you have an XElement, you can extract the array of names of its children using the following code:
string[] names = xElem.Elements().Select(e => e.Name.LocalName).ToArray();
For example, this code with your XML:
public static MyXExtensions
{
public static string[] ChildrenNames(this XElement xElem)
{
return xElem.Elements().Select(e => e.Name.LocalName).ToArray();
}
}
string[] names1 = xDoc.Root.ChildrenNames();
string[] names2 = xDoc.Root.Element("AChau").ChildrenNames();
string[] names3 = xDoc.XPathSelectElement("Location/AChau/ACity").ChildrenNames();
will return the following arrays respectively:
["AChau"]
["ACity", "BCity"]
["EHouse", "FHouse", "GHouse"]
If you're using XElement to get your data from xml - then all you need is FirstNode property and Elements method.
FirstNode returns first child node of element and Elements returns all direct child nodes of element.
This works if you always want the first node name under the root:
string xml = #"<Location>
<AChau>
<ACity>
<EHouse/>
<FHouse/>
<GHouse/>
</ACity>
<BCity>
<HHouse/>
<IHouse/>
<JHouse/>
<KHouse/>
</BCity>
</AChau>
</Location>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlNode root = doc.DocumentElement;
XmlNode first = root.FirstChild;
Try this xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string xml =
"<Location>" +
"<AChau>" +
"<ACity>" +
"<EHouse/>" +
"<FHouse/>" +
"<GHouse/>" +
"</ACity>" +
"<BCity>" +
"<HHouse/>" +
"<IHouse/>" +
"<JHouse/>" +
"<KHouse/>" +
"</BCity>" +
"</AChau>" +
"</Location>";
XElement location = XElement.Parse(xml);
var results = location.Descendants("AChau").Elements().Select(x => new
{
city = x.Name.LocalName,
houses = string.Join(",",x.Elements().Select(y => y.Name.LocalName).ToArray())
}).ToList();
}
}
}
I am using .net 4.0 winforms. In my application a have config file (config.xml), on this file i have lots nodes and child nodes, all are different, i want to select specific node and nodes inside the selected node.
I tried lots of solutions but not succeed.
Thanks in advance for your help.
This should give you the correct result:-
XDocument doc = XDocument.Load(#"XMLFilePath");
XNamespace ns = "http://schemas.datacontract.org/2004/07/Silvio.Settings";
var result = doc.Root.Element(ns + "maintenance_anomalies")
.Descendants(ns + "nom_operation")
.Select(x =>
new
{
NomOperation = (string)x,
statutList = x.Parent.Element(ns + "statuts")
.Elements(ns + "statut")
.Select(z => (string)z).ToList()
}).ToList();
Approach:
From the Xdocument object select the root node which is Main. From this select the Element maintenance_anomalies by including the Namespace associated with it. From there you can select all the descendants of nom_operation and fetch it's value. To find all statut inside nom_operation go back to parent node which is operation and from there select all statut elements.
You can also project a Type instead of anonymous type.
Getting following output:-
I had a couple of issues with your xml. First there is an invalid character so instead of using the Load method. There is also a namespace issue so I used Where method to get the tag maintenance_anomalies.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication53
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string file = File.ReadAllText(FILENAME);
XDocument doc = XDocument.Parse(file);
XElement maintenance_anomalies = doc.Descendants().Where(x => x.Name.LocalName == "maintenance_anomalies").FirstOrDefault();
XNamespace ns = maintenance_anomalies.Name.Namespace;
var results = maintenance_anomalies.Elements(ns + "operation").Select(x => new{
nom_operation = x.Element(ns + "nom_operation").Value,
statut = string.Join(",",x.Descendants(ns + "statut").Select(y => y.Value).ToArray())
}).ToList();
}
}
}
The line below should let u access the node u requested. Use this is your class using System.Xml;
XmlDocument XmlDocObj = new XmlDocument();
XmlNode UserNameNode = XmlDocObj.SelectSingleNode("maintenance_anomalies");