If we have a XML like:
<Data>
<Cars>
<Details>
<Dataset se-datafilter="cars" dv-datamanipulationrequired="false" dv-filtercondition="" dv-sortcolumn="" dv-gettopNrows="" />
<XmlData></XmlData>
</Details>
</Cars>
<Jeeps>
<Details>
<Dataset se-datafilter="jeeps" dv-datamanipulationrequired="false" dv-filtercondition="" dv-sortcolumn="" dv-gettopNrows="" />
<XmlData></XmlData>
</Details>
</Jeeps>
</Data>
What is the best way to retrieve the values of all the attributes stored in <Dataset>
element for sMainTagName. sMainTagName can either have value "Cars" or "Jeeps". Passed from the UI.
I have the following code now:
var cols = doc.XPathSelectElements("/Data/" + sMainTagName + "/Details");
string sDataFilter = String.Empty;
string sFilterCondition = String.Empty;
string sSortCol = String.Empty;
foreach (var att in cols.Elemen开发者_C百科ts("Dataset").Attributes())
{
switch(att.Name.ToString())
{
case "se-datafilter":
sDataFilter = att.Value;
break;
case "dv-filtercondition":
sFilterCondition = att.Value;
break;
case "dv-sortcolumn":
sSortCol = att.Value;
break;
}
}
I'm a fan of Linq to Xml. Here's an example:
static void Main(string[] args)
{
var rawXml =
@"<Data>
<Cars>
<Details>
<Dataset se-datafilter=""cars"" dv-datamanipulationrequired=""false"" dv-filtercondition="""" dv-sortcolumn="""" dv-gettopNrows="""" />
<XmlData></XmlData>
</Details>
</Cars>
<Jeeps>
<Details>
<Dataset se-datafilter=""jeeps"" dv-datamanipulationrequired=""false"" dv-filtercondition="""" dv-sortcolumn="""" dv-gettopNrows="""" />
<XmlData></XmlData>
</Details>
</Jeeps>
</Data>
";
var xDoc = XDocument.Parse(rawXml);
var filterName = "jeeps";
var attrs = xDoc.Descendants("Dataset").Where(
x => string.Equals(x.Attribute("se-datafilter").Value,
filterName,
StringComparison.CurrentCultureIgnoreCase
))
.Attributes();
foreach (var attr in attrs)
{
Console.WriteLine(attr.Value);
}
}
}
How about returning a dictionary, build up from the attributes.
return xdoc.XPathSelectElements("/Data/" + sMainTagName + "/Details/Dataset")
.Attributes()
.ToDictionary(attr => attr.Name, attr => attr.Value);
Personally I wouldn't use XPath to start with. I'd do something like this:
// Note - if an element in this chain doesn't exist, you'll get a
// NullReferenceException
var details = doc.Element("Data")
.Element(mainTagName)
.Element("Details")
.Element("Dataset");
string dataFilter = ((string) details.Attribute("se-datafilter")) ?? "";
string filterCondition= ((string) details.Attribute("dv-filtercondition")) ?? "";
string sortCol = ((string) details.Attribute("dv-sortcolumn")) ?? "";
(I'm assuming there's only one Dataset element, by the way.);
This uses the fact that the explicit string conversion from XAttribute
will return null if the attribute doesn't exist (i.e. you're calling it on a null reference).
Use following XPath: //Dataset/@*
, e.g.:
var doc = XDocument.Load("a.txt");
var sMainTagName = "Cars";
string xPath = "Data/" + sMainTagName + "/Details/Dataset/@*";
var attr = (doc.Document.XPathEvaluate(xPath) as IEnumerable).Cast<XAttribute>();
foreach (var item in attr)
{
Console.WriteLine("{0}: {1}", item.Name, item.Value);
}
精彩评论