XPath查询按日期过滤

时间:2014-02-09 18:42:48

标签: xml xpath msxml msxml6

我有一些示例XML,我根据 date 查询节点。

示例XML文档

<?xml version="1.0" encoding="UTF-16" standalone="yes"?>
<NewDataSet>
    <Table>
        <EmployeeBankGUID>dc396ebe-c8a4-4a7f-85b5-b43c1890d6bc</EmployeeBankGUID>
        <ValidFromDate>2012-02-01T00:00:00-05:00</ValidFromDate>
    </Table>
    <Table>
        <EmployeeBankGUID>2406a5aa-0246-4cd7-bba5-bb17a993042b</EmployeeBankGUID>
        <ValidFromDate>2013-02-01T00:00:00-05:00</ValidFromDate>
    </Table>
    <Table>
        <EmployeeBankGUID>2af49699-579e-4beb-9ab0-a58b4bee3158</EmployeeBankGUID>
        <ValidFromDate>2014-02-01T00:00:00-05:00</ValidFromDate>
    </Table>
</NewDataSet>

所以基本上有三个日期:

  • 2012/2/1
  • 2013年2月1日
  • 2014年2月1日

使用MSXML我可以使用XPath查询查询和筛选这些日期:

/NewDataSet/Table[ValidFromDate>"2013-02-12"]

这样可行,并返回包含一个项目的IXMLDOMNodeList

<Table>
    <EmployeeBankGUID>2af49699-579e-4beb-9ab0-a58b4bee3158</EmployeeBankGUID>
    <ValidFromDate>2014-02-01T00:00:00-05:00</ValidFromDate>
</Table>

除非它不再起作用

使用MSXML的XPath查询;微软在1990年代后期创建的xml变体,在W3C标准化完全不同形式的XPath之前。

DOMDocument doc = new DOMDocument();
//...load the xml...
IXMLDOMNodeList nodes = doc.selectNodes('/NewDataSet/Table[ValidFromDate>"2013-02-12"]');

但是那个版本的MSXML不符合&#34;标准&#34; (因为它是在有标准之前创建的)。 Since 2005 the recommended one, the one that follows the standards, the only one that has features I require是MSXML 6.

这是一个简单的更改,只是实例化DOMDocument60类而不是DOMDocument类:

DOMDocument doc = new DOMDocument60();
//...load the xml...
IXMLDOMNodeList nodes = doc.selectNodes('/NewDataSet/Table[ValidFromDate>"2013-02-12"]');

除了相同的XPath查询,不返回任何内容。

按日期过滤值的&#34;标准符合&#34; 方法是什么?

假装它是一个字符串,你说

您可能会认为我可能认为XML将2013-02-01T00:00:00-05:00视为某种特殊日期,而实际上它是一个字符串。所以也许我应该把它想象成字符串比较。

哪种方法有效,但它不起作用。没有字符串比较工作:

  • /NewDataSet/Table[ValidFromDate<"a"]不返回任何节点
  • /NewDataSet/Table[ValidFromDate>"a"]不返回任何节点
  • /NewDataSet/Table[ValidFromDate!="a"]返回所有节点
  • /NewDataSet/Table[ValidFromDate>"2014-02-12T00:00:00-05:00"]不返回任何节点
  • /NewDataSet/Table[ValidFromDate<"2014-02-12T00:00:00-05:00"]不返回任何节点
  • /NewDataSet/Table[ValidFromDate!="2014-02-12T00:00:00-05:00"]不返回任何节点

所以,我们有它

什么是符合&#34;标准&#34; 的方式来实现以前的工作?

对于日期字符串的XPath查询,&#34;正确&#34; 的方式是什么?

或者,更好的是,为什么我的XPath查询不起作用?

或者,更好更好,为什么过去工作的查询不再有效?决定语法错误的决定是什么?他们通过&#34;打破&#34; 查询语法解决了什么边缘案例?

MSXML6兼容版本

这是最终的功能代码,几乎与我使用的语言相同:

DOMDocument60 GetXml(String url)
{
   XmlHttpRequest xml = CoServerXMLHTTP60.Create();
   xml.Open('GET', url, False, '', '');
   xml.Send(EmptyParam);

   DOMDocument60 doc = xml.responseXML AS DOMDocument60;

   //MSXML6 removed all kinds of features originally present (thanks W3C)
   //Need to use Microsoft's proprietary extensions to get some of it back (thanks W3C)
   doc.setProperty('SelectionNamespaces', 'xmlns:ms="urn:schemas-microsoft-com:xslt"');

   return doc;
}


DOMDocument doc = GetXml('http://example.com/GetBanks.ashx?employeeID=12345');

//Finds future banks. 

//Only works in MSXML3; intentionally broken in MSXML6 (thanks W3C):
//String qry = '/NewDataSet/Table[ValidFromDate > "2014-02-12"]';

//MSXML6 compatible version of doing the above (send complaints to W3C);
String qry = '/NewDataSet/Table[ms:string-compare(ValidFromDate, "2014-02-12") >= 0]';

IXMLDOMNodeList nodes = doc.selectNodes(qry);

1 个答案:

答案 0 :(得分:4)

XPath不是日期识别

  

对于日期字符串的XPath查询,&#34;正确&#34; 的方式是什么?

在XPath 1.0中,没有办法处理日期字符串,只考虑时区支持。至少没有正确的方式来处理它们。如果时区不同,比较字符串将失败。

比较字符串

  

或者,更好的是,为什么我的XPath查询不起作用?

XPath 1.0仅定义字符串上的相等运算符,大于/小于值have to be converted to numbers

使用MSXML 4.0中引入的ms:string-compare

/NewDataSet/Table[
  ms:string-compare(ValidFromDate, "2014-02-12T00:00:00-05:00") > 0
]

对于(XML)世界的其余部分

  

什么是符合&#34;标准&#34; 的方式来实现以前的工作?

替代方案也可以在其他XPath实现中使用(我使用xmllint测试它,使用libxml)可能会translate远离所有非字符串字符,因此该字符串将可解析为数字:

/NewDataSet/Table[
  translate(ValidFromDate, "-:T", "") < translate("2014-02-12T00:00:00-05:00", "-:T", "")
]