5

dateに基づいてノードを照会しているサンプル XML があります。

サンプル 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>

したがって、基本的に3つの日付があります。

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

MSXML を使用すると、XPath クエリを使用してこれらの日付でクエリとフィルター処理を行うことができます。

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

そして、これは機能し、IXMLDOMNodeList1 つのアイテムを含むものを返します。

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

もう機能しないことを除いて

MSXML を使用したその XPath クエリ。W3C が XPath の完全に異なる形式で標準化する前の 1990 年代後半に Microsoft が作成した xml のバリアント。

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

しかし、そのバージョンの MSXML は「標準準拠」ではありません(標準が存在する前に作成されたため)。2005 年以来、推奨されているもの、標準に準拠しているもの、私が必要とする機能を備えているのは MSXML 6 だけです。

これは簡単な変更です。DOMDocument60クラスではなくクラスをインスタンス化するだけDOMDocumentです。

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

ただし、同じ XPath クエリでは何も返されません。

日付で値をフィルタリングする「標準に準拠した」方法は何ですか?

それは文字列のふりをします、あなたは言います

2013-02-01T00:00:00-05:00実際には文字列であるのに、XML は をある種の特別な日付として扱っていると私が考えているのではないかと思われるかもしれません。ですから、文字列比較のように考えるべきかもしれません。

それが機能しないことを除いて、これは機能します。文字列比較は機能しません:

  • /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"]ノードを返しません

では、ここまでです

以前は機能していたものを達成するための「標準に準拠した」方法は何ですか?

日付文字列のXPathクエリの「正しい」方法は何ですか?

または、XPath クエリが機能しないのはなぜですか?

または、さらに良いことに、以前は機能していたクエリが機能しなくなったのはなぜですか? 構文が悪いと判断した決定は何でしたか。クエリ構文を「壊す」ことで解決していたエッジケースは何ですか?

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);
4

1 に答える 1

4

XPath は日付に対応していません

日付文字列のXPathクエリの「正しい」方法は何ですか?

XPath 1.0 では、日付文字列を処理する方法はありません。タイム ゾーンのサポートについて考えてみてください。少なくとも、それらを処理する正しい方法はありません。タイムゾーンが異なる場合、文字列の比較は失敗します。

文字列の比較

または、XPath クエリが機能しないのはなぜですか?

XPath 1.0 は文字列に対してのみ等値演算子を定義します。値よりも大きい/小さい場合は数値に変換する必要があります

ms:string-compareMSXML 4.0 で導入されたものを使用します。

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

(XML) の世界の残りの部分について

以前は機能していたものを達成するための「標準に準拠した」方法は何ですか?

他の XPath 実装でも機能する代替手段 (私xmllintは を使用してテストしましたlibxml) はtranslate、文字列以外のすべての文字を取り除くことである可能性があるため、文字列は数値として解析可能になります。

/NewDataSet/Table[
  translate(ValidFromDate, "-:T", "") < translate("2014-02-12T00:00:00-05:00", "-:T", "")
]
于 2014-02-09T18:49:41.247 に答える