XPath-Abfrage die Filterung nach Datum
Habe ich einige Beispiel-XML, wo ich die Abfrage für den Knoten basierend auf einem Datum.
Beispiel-XML-Dokument:
<?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>
Also grundsätzlich gibt es drei Termine:
- 2/1/2012
- 2/1/2013
- 2/1/2014
Mithilfe von MSXML kann ich die Abfrage und filter, indem Sie diese Daten mithilfe einer XPath-Abfrage:
/NewDataSet/Table[ValidFromDate>"2013-02-12"]
Funktioniert, und gibt einen IXMLDOMNodeList
mit einem Eintrag:
<Table>
<EmployeeBankGUID>2af49699-579e-4beb-9ab0-a58b4bee3158</EmployeeBankGUID>
<ValidFromDate>2014-02-01T00:00:00-05:00</ValidFromDate>
</Table>
Außer es funktioniert nicht mehr
XPath-Abfrage mithilfe von MSXML verwenden; die Variante von xml, die von Microsoft erstellt, die in den späten 1990er Jahren, bevor die W3C standardisiert auf eine ganz andere form von XPath.
DOMDocument doc = new DOMDocument();
//...load the xml...
IXMLDOMNodeList nodes = doc.selectNodes('/NewDataSet/Table[ValidFromDate>"2013-02-12"]');
Aber, dass die version von MSXML ist nicht "Standard-konformes" (seit es erstellt wurde, bevor es-Normen). Seit 2005 ist die empfehlenswert, der einem folgt, dass die standards, die einzige, die Funktionen, die ich benötigen ist MSXML 6.
Es ist eine einfache änderung, nur ein Exemplar einer DOMDocument60
Klasse eher als eine DOMDocument
Klasse:
DOMDocument doc = new DOMDocument60();
//...load the xml...
IXMLDOMNodeList nodes = doc.selectNodes('/NewDataSet/Table[ValidFromDate>"2013-02-12"]');
Außer dem gleichen XPath-Abfrage nichts zurückgibt.
Was ist der "Standard-konformes" Weg zur Filterung einen Wert von Datum?
So tun, es ist eine Zeichenfolge, die Sie sagen
Könnte man denken, dass ich könnte denken, dass XML die Behandlung der 2013-02-01T00:00:00-05:00
als eine Art von besonderer Tag, wenn in Wirklichkeit ist es ein string. Also vielleicht sollte ich einfach denke, dass es wie ein string-Vergleiche.
Welche funktionieren würde, außer dass es nicht funktioniert. Keine string-Vergleich funktioniert:
/NewDataSet/Table[ValidFromDate<"a"]
gibt keine Knoten/NewDataSet/Table[ValidFromDate>"a"]
gibt keine Knoten/NewDataSet/Table[ValidFromDate!="a"]
gibt alle Knoten/NewDataSet/Table[ValidFromDate>"2014-02-12T00:00:00-05:00"]
gibt keine Knoten/NewDataSet/Table[ValidFromDate<"2014-02-12T00:00:00-05:00"]
gibt keine Knoten/NewDataSet/Table[ValidFromDate!="2014-02-12T00:00:00-05:00"]
gibt keine Knoten
So, da haben wir es
Was ist der "Standard-konformes" Weg, das zu erreichen, was verwendet werden, um zu arbeiten?
Was ist der "richtige" Weg, um XPath-Abfragen für Datums-strings?
Oder, besser noch, warum sind meine XPath-Abfragen nicht funktioniert?
Oder, besser besser doch, warum die Abfrage, die funktioniert haben, funktionieren nicht mehr? Was war die Entscheidung, die gemacht wurde, die beschlossen, die syntax war schlecht. Was waren edge Fällen waren Sie der Lösung des durch "brechen" die Abfrage-syntax?
MSXML6 kompatible version
Hier das Finale funktionalen code, fast in der Sprache, die ich benutze:
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);
Du musst angemeldet sein, um einen Kommentar abzugeben.
XPath ist nicht Datum-bewusst
In XPath 1.0 gibt es keine Möglichkeit zur Handhabung von Datums-Zeichenketten, denken Sie nur an Zeit-zone unterstützen. Zumindest gibt es keine richtigen Weg, um Sie zu behandeln. Vergleichen von Zeichenfolgen wird scheitern, wenn die Zeitzonen unterschiedlich sind.
Vergleichen von strings
XPath 1.0 definiert nur die Gleichheit von Operatoren auf strings, für größer/kleiner als die Werte müssen in zahlen umgewandelt werden.
Verwenden
ms:string-vergleichen
wurde in MSXML 4.0.Für den rest der (XML -) Welt
Einer alternative, die funktioniert auch in anderen XPath-Implementierungen (getestet habe ich es mit
xmllint
verwendetlibxml
) könnte es seintranslate
entfernt alle nicht-string-Zeichen, so wird die Zeichenfolge parseable als Zahl:doc.setProperty("SelectionNamespaces", "xmlns:ms='urn:schemas-microsoft-com:xslt'");
.SelectionNamespaces
löste das Letzte Stück.