在c#中使用“复杂”XPath

时间:2013-04-17 20:21:01

标签: c# xpath

我有这个非常简单的XML

<Customer>
   <BirthDate>1958-05-31 00:00:00</BirthDate>
</Customer>

我想在没有小时部分的情况下提取BirthDate。

编辑:必须在XPath语句中完成,而不是在客户端代码中完成。

我已使用此website测试此XPath:

/Customer/BirthDate/substring(text(), 1, 10)

我也测试了这个XPath:

/Customer/BirthDate/substring(., 1, 10)

该网站给了我预期的结果。但是我的C#程序给了我一个运行时错误。

这是测试程序:

var content = @"<Customer><BirthDate>1958-05-31 00:00:00</BirthDate></Customer>";

using (var memStream = new MemoryStream(Encoding.Default.GetBytes(content)))
{
    var doc = new XPathDocument(memStream);
    var navigator = doc.CreateNavigator();

    /// GET THE "RAW" VALUE. WORKING
    var expr = navigator.Compile("/Customer/BirthDate");
    var iter = navigator.Select(expr);
    Console.WriteLine("BirthDate: {0}", iter.Current.Value);

    /// GET THE "TRANSFORMED" VALUE. NOT WORKING
    var expr2 = navigator.Compile("/Customer/BirthDate/substring(text(), 1, 8)");
    var iter2 = navigator.Select(expr2);
    Console.WriteLine("BirthDate: {0}", iter2.Current.Value);

    Console.ReadKey();
}

这是一个XPathException,没有任何关于消息的内在感知:

  

'/ Customer / BirthDate / substring(text(),1,10)'的标记无效。

Wellllllll .....我该怎么办?

5 个答案:

答案 0 :(得分:2)

  

编辑:必须在XPath语句中完成,而不是在客户端代码中完成。

.net内置的XPath支持仅支持XPath 1.0。 XPath 1.0不支持位置步骤中的函数,因此您必须使用支持XPath 2.0的.net的第三方库,如XmlPrimeSaxxonQuery Machine

答案 1 :(得分:1)

我会选择你的第一个选择。选择值,将字符串解析为日期,然后格式化日期。而不是一次性完成这一切。

 var expr = navigator.Compile("/Customer/BirthDate");
 var iter = navigator.Select(expr);
 var formatted dates = iter
             .Select(i=>i.Current.Value)
             .Select(x => DateTime.Parse(x))
             .Select(x=> d.ToString(put desired format here))
             .ToArray();

答案 2 :(得分:1)

您可以像这样评估单个值:

var expr2 = navigator.Evaluate("substring(/Customer/BirthDate, 1, 10)");
Console.WriteLine(expr2);

但这只会给你一个字符串。

以下表达式似乎编译并返回一个节点集,但没有提取子字符串,总是返回完整的字符串:

var expr2 = navigator.Compile("/Customer/BirthDate[substring(text(), 1, 8)]");

答案 3 :(得分:1)

使用:

substring(/Customer/BirthDate, 1, 10)

在XPath 1.0中有效。

正如Philip的回答所指出的那样,你尝试过的语法在XPath 2.0中是有效的,但在1.0中则没有,那就是.NET支持的版本

答案 4 :(得分:0)

我不知道你为什么不简单地使用:

var doc = new XPathDocument(memStream);
            var navigator = doc.CreateNavigator();

            /// GET THE "RAW" VALUE. WORKING
            var expr = navigator.Compile("/Customer/BirthDate");
            var iter = navigator.Select(expr);
            Console.WriteLine("BirthDate: {0}", iter.Current.Value);

            /// GET THE "TRANSFORMED" VALUE. NOT WORKING
            var result = iter.Current.Value.ToString().Substring(0, 10);
            Console.WriteLine("BirthDate: {0}", result);   

将子字符串值放在一个新的var中,然后你会用它做任何你想做的事。