如何在可以是XElement或XAttribute时强制转换XPathEvalute?

时间:2012-09-30 08:59:25

标签: c# .net xml xpath

所以我有这段代码:

List<PriceDetail> prices =
                (from item in xmlDoc.Descendants(shop.DescendantXName)
                 select new PriceDetail
                 {
                     Price = GetPrice(item.Element(shop.PriceXPath).Value),
                     GameVersion = GetGameVersion(((IEnumerable)item.XPathEvaluate(shop.TitleXPath)).Cast<XAttribute>().First<XAttribute>().Value, item.Element(shop.PlatformXPath).Value),
                     Shop = shop,
                     Link = item.Element(shop.LinkXPath).Value,
                     InStock = InStock(item.Element(shop.InStockXPath).Value)
                 }).ToList<PriceDetail>();

我遇到的问题是这段代码:

((IEnumerable)item.XPathEvaluate(shop.TitleXPath)).Cast<XAttribute>().First<XAttribute>().Value

有时来自XPathEvaluate的对象可能是XElement,然后转换不起作用。所以我需要的是一个适用于XAttribute和XElement的Cast。

有什么建议吗?

4 个答案:

答案 0 :(得分:14)

更改您的XPath表达式(shop.TitleXPath
  someXPathExpression

  string(someXPathExpression)

然后您可以将代码简化为

string result = item.XPathEvaluate(shop.TitleXPath) as string;

完整的工作示例

using System;
using System.IO;
using System.Xml.Linq;
using System.Xml.XPath;

class TestXPath
{
    static void Main(string[] args)
    {

        string xml1 =
@"<t>
 <a b='attribute value'/> 
 <c>
   <b>element value</b>
 </c>
 <e b='attribute value'/>
</t>";

        string xml2 =
@"<t>
 <c>
   <b>element value</b>
 </c>
 <e b='attribute value'/>
</t>";

        TextReader sr = new StringReader(xml1);
        XDocument xdoc = XDocument.Load(sr, LoadOptions.None);

        string result1 = xdoc.XPathEvaluate("string(/*/*/@b | /*/*/b)") as string;

        TextReader sr2 = new StringReader(xml2);
        XDocument xdoc2 = XDocument.Load(sr2, LoadOptions.None);

        string result2 = xdoc2.XPathEvaluate("string(/*/*/@b | /*/*/b)") as string;

        Console.WriteLine(result1);
        Console.WriteLine(result2);


    }
}

当执行该程序时,相同的XPath表达式应用于两个不同的XML文档,并且无论string()的参数是第一次的属性并且是第二次的元素,我们获得正确的结果 - 写入控制台:

attribute value
element value

答案 1 :(得分:7)

XElementXAttribute都是XObject的形式,因此如果XObject类型的通用实例足以满足您的需求,请更改您的投放<XAttribute>施展<XObject>

如果这不适用于您的具体情况,您可以使用OfType <XAttribute>或OfType <XElement>来过滤一个或另一个,但这需要两次通过输入,一个过滤XElement,第二遍过滤XAttribute

答案 2 :(得分:4)

如果找不到元素,Dimitre的解决方案将返回空字符串;我们无法将其与实际的空值区分开来。所以我必须使这个扩展方法通过XPath查询处理多个结果,如果没有找到则返回空枚举:

public static IEnumerable<string> GetXPathValues(this XNode node, string xpath)
{
    foreach (XObject xObject in (IEnumerable)node.XPathEvaluate(xpath))
    {
        if (xObject is XElement)
            yield return ((XElement)xObject).Value;
        else if (xObject is XAttribute)
            yield return ((XAttribute)xObject).Value;
    }
}

答案 3 :(得分:1)

在进行演员表之前,您可以使用以下代码检查类型:

XElement e = item as XElement;
XAttribute a = item as XAttribute;

if(e != null)
   //item is of type XElement
else
  //item is of type XAttribute