代码之家  ›  专栏  ›  技术社区  ›  gkrogers

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

  •  2
  • gkrogers  · 技术社区  · 15 年前

    我有一个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()

    但不知道怎么说“国家日期”=最早的国家日期。

    有人能给我指个方向吗?

    解决方案: 马特的解决方案或多或少是恰到好处的。我必须重新格式化日期(我使用了YYYYMMDDD),因为正如前面指出的那样,xpath 1.0不支持我使用的日期格式。此外,Microsoft的XML库(4.0和6.0)返回了带有Matt表达式的整个节点列表。反向测试解决了这个问题,使它只返回最早的节点。

    所以:

    //STATES/STATE[(DATEOFSTATEHOOD < //STATES/STATE/DATEOFSTATEHOOD)]/CAPITAL/text()
    
    3 回复  |  直到 15 年前
        1
  •  3
  •   Matt Weldon    15 年前

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

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

        2
  •  1
  •   Dave Cassel    15 年前

    你能把它们重新格式化为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服务器中完成,但我认为这都是标准配置。

        3
  •  1
  •   Chris Wallace    15 年前

    可以使用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 sandbox