Как получить максимальное значение определенного тега в файле XML с помощью SimpleXML? - PullRequest
1 голос
/ 18 января 2011

Мой XML-файл выглядит так:

<log>
  <entry entry_id="E200911115777">
    <entry_data>
      <entry_title>Lorem ipsum dolor</entry_title>
      <entry_date>1999-04-15</entry_date>
    </entry_data>
  </entry>
  <entry entry_id="E205011115999">
    <entry_data>
      <entry_title>Lorem ipsum dolor</entry_title>
      <entry_date>2004-12-15</entry_date>
    </entry_data>
  </entry>
  <entry entry_id="E199912119116">
    <entry_data>
      <entry_title>Lorem ipsum dolor</entry_title>
      <entry_date>1990-11-20</entry_date>
    </entry_data>
  </entry>
</log>

Я ищу код, который вернет наибольшее значение тега entry_date , в данном случае 2004-12-15 . Я использую SimpleXML, но я открыт для других решений, конечно. Приветствия.

Ответы [ 3 ]

3 голосов
/ 18 января 2011

I. Вот простое решение XSLT 1.0, наиболее близкое к использованию одного выражения XPath (невозможно иметь только одно выражение XPath 1.0 для выбора нужного узла (узлов)):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="entry">
  <xsl:copy-of select=
   "self::node()
      [not((preceding-sibling::entry | following-sibling::entry)
             [translate(*/entry_date,'-','')
             >
             translate(current()/*/entry_date,'-','')
             ]
           )
      ]
   "/>
 </xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к предоставленному документу XML :

<log>
    <entry entry_id="E200911115777">
        <entry_data>
            <entry_title>Lorem ipsum dolor</entry_title>
            <entry_date>1999-04-15</entry_date>
        </entry_data>
    </entry>
    <entry entry_id="E205011115999">
        <entry_data>
            <entry_title>Lorem ipsum dolor</entry_title>
            <entry_date>2004-12-15</entry_date>
        </entry_data>
    </entry>
    <entry entry_id="E199912119116">
        <entry_data>
            <entry_title>Lorem ipsum dolor</entry_title>
            <entry_date>1990-11-20</entry_date>
        </entry_data>
    </entry>
</log>

желаемый, правильный результат получается :

<entry entry_id="E205011115999">
   <entry_data>
      <entry_title>Lorem ipsum dolor</entry_title>
      <entry_date>2004-12-15</entry_date>
   </entry_data>
</entry>

II. Более эффективное решение XSLT 1.0:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
  <xsl:apply-templates>
   <xsl:sort order="descending"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="entry">
  <xsl:if test="position() = 1">
   <xsl:copy-of select="."/>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к тому же XML-документу (см. Выше), снова получается требуемый, правильный результат :

<entry entry_id="E205011115999">
   <entry_data>
      <entry_title>Lorem ipsum dolor</entry_title>
      <entry_date>2004-12-15</entry_date>
   </entry_data>
</entry>
1 голос
/ 18 января 2011
$result = $xml->xpath('//entry_date');

usort($result,'strcmp');

$maxdate = end($result);
1 голос
/ 18 января 2011

Да, с xpath должно быть довольно легко, это определенно путь, и простой xml хорошо работает с xpath в php.

Проверьте документы здесь: http://www.php.net/manual/en/simplexmlelement.xpath.php

$xml = new SimpleXMLElement($string);

/* Search for <log><entry><entry_data><entry_date> */
$result = $xml->xpath('/log/entry/entry_data/entry_date');

while(list( , $node) = each($result)) {
    $timestamp = strtotime((string) $node));
    echo '/log/entry/entry_data/entry_date: ' . $timestamp ."\n";
}

На самом деле я не тестировал этот код, но он должен быть достаточно близок к тому, что вам нужно, и временные метки, конечно, имеют свои пределы, но, похоже, подходят для вашего использования.

...