Выражение Xpath для извлечения самого старого / самого раннего узла - PullRequest
2 голосов
/ 09 июня 2010

У меня есть фрагмент XML, поэтому:

<STATES>
  <STATE>
    <NAME>Alabama</NAME>
    <ABBREVIATION>AL</ABBREVIATION>
    <CAPITAL>Montgomery</CAPITAL>
    <POPULATION>4661900</POPULATION>
    <AREA>52419</AREA>
    <DATEOFSTATEHOOD>14 December 1819</DATEOFSTATEHOOD>
  </STATE>
  <STATE>
    <NAME>Alaska</NAME>
    <ABBREVIATION>AK</ABBREVIATION>
    <CAPITAL>Juneau</CAPITAL>
    <POPULATION>698473</POPULATION>
    <AREA>663268</AREA>
    <DATEOFSTATEHOOD>1 January 1959</DATEOFSTATEHOOD>
  </STATE>
  <STATE>
    <NAME>Delaware</NAME>
    <ABBREVIATION>DE</ABBREVIATION>
    <CAPITAL>Dover</CAPITAL>
    <POPULATION>885122</POPULATION>
    <AREA>2490</AREA>
    <DATEOFSTATEHOOD>7 December 1787</DATEOFSTATEHOOD>
  </STATE>
</STATES>
<etc, etc.>

Я хочу получить (например) столицу самого старого штата (например, "Дувр").Мне удалось пройти это далеко:

//STATES/STATE[DATEOFSTATEHOOD='7 December 1787']/CAPITAL/text()

, но я не могу понять, как сказать 'DATEOFSTATEHOOD = {самый ранний DATEOFSTATEHOOD}'.

Может кто-нибудьНаправьте меня в правильном направлении, пожалуйста?

РЕШЕНИЕ: Решение Мэтта более или менее актуально.Мне пришлось переформатировать даты (я использовал ГГГГММДДД), потому что, как было указано, Xpath 1.0 не поддерживает формат даты, который я использовал.Кроме того, XML-библиотека Microsoft (4.0 и 6.0) вернула весь список узлов с выражением Мэтта.Сторнирование теста устранило эту проблему, заставив вернуть только самый ранний узел.

Итак:

//STATES/STATE[(DATEOFSTATEHOOD < //STATES/STATE/DATEOFSTATEHOOD)]/CAPITAL/text()

Ответы [ 3 ]

3 голосов
/ 09 июня 2010

XPATH 1.0 не поддерживает даты в указанном вами формате. Если бы вы могли использовать числовое представление этих дат, например 17871207, то вы могли бы легко сделать это так:

//STATES/STATE[not(DATEOFSTATEHOOD > //STATES/STATE/DATEOFSTATEHOOD)]/CAPITAL/text()

Если это невозможно, возможно, стоит попытаться отформатировать узел DATEOFSTATEHOOD как xs:date и выполнить то же самое:

//STATES/STATE[not(xs:date(DATEOFSTATEHOOD) > xs:date(//STATES/STATE/DATEOFSTATEHOOD))]/CAPITAL/text()

Синтаксис может быть не совсем правильным, но, надеюсь, он поможет вам начать работу.

1 голос
/ 11 июня 2010

Вы можете переформатировать дату с помощью XQuery и использовать min (), чтобы найти самую раннюю дату:

declare variable $monthnames := ("January","February","March","April","May","June","July","August","September","October","November","December");

declare function local:pad-zero($s as xs:string) as xs:string {
  if (string-length($s) = 1) then concat("0",$s) else $s
};

declare function local:df ($d as xs:string) as xs:date {
  let $dp := tokenize($d," ")
  let $year := $dp[3]
  let $month := local:pad-zero(string(index-of($monthnames,$dp[2])))
  let $day := local:pad-zero($dp[1])
  return
    concat($year,"-",$month,"-",$day)


};

let $states := 
<STATES>
  <STATE>
    <NAME>Alabama</NAME>
    <ABBREVIATION>AL</ABBREVIATION>
    <CAPITAL>Montgomery</CAPITAL>
    <POPULATION>4661900</POPULATION>
    <AREA>52419</AREA>
    <DATEOFSTATEHOOD>14 December 1819</DATEOFSTATEHOOD>
  </STATE>
  <STATE>
    <NAME>Alaska</NAME>
    <ABBREVIATION>AK</ABBREVIATION>
    <CAPITAL>Juneau</CAPITAL>
    <POPULATION>698473</POPULATION>
    <AREA>663268</AREA>
    <DATEOFSTATEHOOD>1 January 1959</DATEOFSTATEHOOD>
  </STATE>
  <STATE>
    <NAME>Delaware</NAME>
    <ABBREVIATION>DE</ABBREVIATION>
    <CAPITAL>Dover</CAPITAL>
    <POPULATION>885122</POPULATION>
    <AREA>2490</AREA>
    <DATEOFSTATEHOOD>7 December 1787</DATEOFSTATEHOOD>
  </STATE>
</STATES>


return 
   $states//STATE
     [local:df(DATEOFSTATEHOOD) = 
      min($states//STATE/local:df(DATEOFSTATEHOOD))
     ]

Вы можете выполнить это в песочнице eXist

1 голос
/ 09 июня 2010

Можете ли вы переформатировать их в xs: даты?

let $dates := (xs:date('2000-10-23'), xs:date('1999-12-26'))
let $min := fn:min($dates)
let $max := fn:max($dates)
return $min

Готово в MarkLogic Server, но я думаю, что это все стандартные вещи.

...