用于检索最旧/最早节点的 Xpath 表达式

发布于 2024-09-05 17:15:48 字数 1524 浏览 11 评论 0原文

我有一个 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={最早建国日期}'。

有人能指出我正确的方向吗?

解决方案:马特的解决方案或多或少是正确的。我必须重新格式化日期(我使用 YYYYMMDDD),因为正如所指出的,Xpath 1.0 不支持我使用的日期格式。此外,Microsoft 的 XML 库(4.0 和 6.0)还返回了包含 Matt 表达式的整个节点列表。逆向测试解决了这个问题,使其仅返回最早的节点。

所以:

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

I have an XML snippet, so:

<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.>

I want to retrieve (for example) the capital of the oldest state (i.e. "Dover").
I have managed to get this far:

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

but can't figure out how to say 'DATEOFSTATEHOOD={the earliest DATEOFSTATEHOOD}'.

Can anybody point me in the right direction, please?

SOLUTION: Matt's solution is more or less spot on. I had to reformat the dates (I used YYYYMMDDD) because, as was pointed out, Xpath 1.0 doesn't support the date format I was using. Also, Microsoft's XML library (4.0 and 6.0) returned the whole node list with Matt's expression. Reversing the test fixed that problem, making it return just the earliest node.

So:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小糖芽 2024-09-12 17:15:48

XPATH 1.0 不支持您提供的格式的日期。如果您能够使用这些日期的数字表示形式,例如 17871207,那么您可以轻松地这样做:

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

如果这不可行,那么可能值得尝试将 DATEOFSTATEHOOD 节点格式化为 < code>xs:date 并执行相同的操作:

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

语法可能不完全正确,但希望它能帮助您入门。

XPATH 1.0 does not support dates in the format that you are providing. If you were able to use a numerical representation of these dates such as 17871207 then you could easily do it like so:

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

If this is not feasible then it might be worth trying to format the DATEOFSTATEHOOD node as an xs:date and performing the same:

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

The syntax may not be entirely correct but hopefully it'll get you started.

难如初 2024-09-12 17:15:48

您可以将它们重新格式化为 xs:dates 吗?

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 中完成,但我认为这都是标准的东西。

Can you reformat them to be xs:dates?

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

Done in MarkLogic Server, but I think that's all standard stuff.

倾城月光淡如水﹏ 2024-09-12 17:15:48

您可以使用 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 沙箱

You can reformat the date with XQuery and use min() to locate the earliest date:

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))
     ]

You can execute this in the eXist sandbox

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文