2

I have next xml:

<Histories>
    <History>
        <Date>20.06.2010</Date>
        <FileName>4.txt</FileName>
    </History>
    <History>
        <Date>05.06.2012</Date>
        <FileName>2.txt</FileName>
    </History>
    <History>
        <Date>18.12.1999</Date>
        <FileName>3.txt</FileName>
    </History>
</Histories>

I need to get last node by date (set XPath witch return date). How can I do? Example: 2.txt

Thanks

WPF-it
  • 19,625
  • 8
  • 55
  • 71
ShurikEv
  • 170
  • 1
  • 10
  • >/Histories/History[ not( (preceding-sibling::History | following-sibling::History)/Date > Date ) ] not work for my formate date – ShurikEv Mar 28 '12 at 05:38
  • Indeed. It is not possible to do this with your date-format in just XPath 1.0. Alternatives offered are: XPath 2.0, LINQ to XML, XSLT and XQuery. – Markus Jarderot Mar 28 '12 at 05:47

4 Answers4

3

In XPath 2.0 you can do it like this:

/Histories/History[
    concat(substring(Date,7),substring(Date,4,2),substring(Date,1,2)) =
    max(/Histories/History/concat(substring(Date,7),substring(Date,4,2),
        substring(Date,1,2)))
]

The first part (concat(...)) converts the date into YYYYMMDD format to allow sorting. It then compares it to the maximum such value in the file.

This would not be possible in XPath 1.x, since there are no max() function, nor can you call functions at the end of a path (/Histories/History/concat(...)).

Natively, .NET does not support XPath 2.0, but there are libraries that add this.

Community
  • 1
  • 1
Markus Jarderot
  • 86,735
  • 21
  • 136
  • 138
  • 1
    +1. If the OP had useful date formats, this would be pretty simple in XPath 1.0. I've added an "if only"-solution. – Tomalak Mar 19 '12 at 08:32
2

This is not specific to WPF.

Did you try using XQuery or XLinq for this?

        var element = XElement.Parse(<yourXml>);
        var lastDateHistoryNode
              = element.XPathSelectElements("//History").OrderByDescending(
                   e => DateTime.ParseExact(
                          e.Element("Date").Value, "dd.MM.yyyy", null)).First();
        var lastDateFileName = lastDateHistoryNode.Element("FileName").Value;
WPF-it
  • 19,625
  • 8
  • 55
  • 71
2

If you had proper dates in your XML (yyyyddmm instead of dd.mm.yyyy), this XPath 1.0 would work:

/Histories/History[
  not(
    (preceding-sibling::History | following-sibling::History)/Date > Date
  )
]

Since you have your dates the wrong way, XPath 1.0 cannot do this.

Tomalak
  • 332,285
  • 67
  • 532
  • 628
0

XPath on its own won't allow you to select from an ordered list. If you can use XSLT first (in particular <xsl:sort>) to obtain a sorted node-set, then selecting the first or last element is trivial (nodeset[1] or nodeset[last()].

To have the dates sorted chronologically it's also wise to convert them to ISO first (YYYY-MM-DD) as then the string order coincides with the chronological order.

hroptatyr
  • 4,702
  • 1
  • 35
  • 38
  • XPath does not let you select from an ordered list, but there are ways to get the minimum/maximum value from a node set - as long as the values sort naturally (which `dd.mm.yyyy` does not do, unfortunately). – Tomalak Mar 19 '12 at 08:35