Как найти начальную (минимальную) и конечную (максимальную) дату в XML-файле? - PullRequest
2 голосов
/ 12 апреля 2011

У меня есть файл XML.Я должен найти для того же поля2 дату начала (мин) и дату окончания (макс) из поля3.Может быть, у xsl есть какая-то функция, чтобы найти его. Потому что я пытаюсь сделать это, пытаясь найти минимальный месяц и минимальный день и максимальный месяц, максимальный день.XML:

<document>
    <line id="0">
        <field id="2">X111</field>
        <field id="3">2011-03-31</field>
    </line>
    <line id="1">
        <field id="2">X111</field>
        <field id="3">2011-04-04</field>
    </line>
    <line id="2">
        <field id="2">X111</field>
        <field id="3">2011-04-02</field>
    </line>
    <line id="3">
        <field id="2">X222</field>
        <field id="3">2011-04-04</field>
    </line>
    <line id="4">
        <field id="2">X222</field>
        <field id="3">2011-04-01</field>
    </line>
    <line id="4">
        <field id="2">X333</field>
        <field id="3">2011-04-01</field>
    </line>
</document>

Вывод:

<document>
<Message>
    <ID>X111</ID>
    <dateStart>2011-03-31</dateStart>
    <dateEnd>2011-04-04</dateEnd>
</Message>
<Message>
    <ID>X222</ID>
    <dateStart>2011-04-01</dateStart>
    <dateEnd>2011-04-04</dateEnd>
</Message>
<Message>
    <ID>X333</ID>
    <dateStart>2011-04-01</dateStart>
    <dateEnd>2011-04-01</dateEnd>
</Message>
</document>

Пожалуйста, помогите решить эту проблему.Я работаю с таблицей стилей version = "1.0".

Ответы [ 3 ]

3 голосов
/ 12 апреля 2011

Вероятно, это можно оптимизировать, но он возвращает запрошенные результаты:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:key name="test" match="line" use="field[@id=2]"/>
    <xsl:template match="/">
        <document>
            <xsl:for-each select="//line[generate-id()=generate-id(key('test',field[@id=2]))]">
                <xsl:sort select="field[@id=2]"/>
                <Message>
                    <ID>
                        <xsl:value-of select="field[@id=2]"/>
                    </ID>
                    <xsl:apply-templates select="key('test',field[@id=2])">
                        <xsl:sort select="field[@id=3]"/>
                    </xsl:apply-templates>
                </Message>
            </xsl:for-each>
        </document>
    </xsl:template>
    <xsl:template match="line">
        <xsl:if test="position()=1">
            <dateStart>
                <xsl:value-of select="field[@id=3]"/>
            </dateStart>
        </xsl:if>
        <xsl:if test="position()=last()">
            <dateEnd>
                <xsl:value-of select="field[@id=3]"/>
            </dateEnd>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>
2 голосов
/ 12 апреля 2011

Я проголосовал за ответ @ mousio, но я бы предпочел, чтобы первый из каждого типа line обрабатывался в своем собственном шаблоне.Итак, в духе TMTOWTDI, вот как я бы это сделал:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
    <xsl:key name="byField2" match="line" use="field[@id=2]" />
    <xsl:template match="/">
        <document>
            <xsl:apply-templates select="document/line" />
        </document>
    </xsl:template>
    <xsl:template match="line[count(.|key('byField2', field[@id=2])[1])=1]">
        <Message>
            <ID><xsl:value-of select="field[@id=2]" /></ID>
            <xsl:apply-templates select="key('byField2', field[@id=2])" mode="m">
                <xsl:sort select="field[@id=3]" />
            </xsl:apply-templates>
        </Message>
    </xsl:template>
    <xsl:template match="line" mode="m">
        <xsl:if test="position()=1">
            <dateStart><xsl:value-of select="field[@id=3]" /></dateStart>
        </xsl:if>
        <xsl:if test="position()=last()">
            <dateEnd><xsl:value-of select="field[@id=3]" /></dateEnd>
        </xsl:if>
    </xsl:template>
    <xsl:template match="line" />
</xsl:stylesheet>

Я думаю, что это легче читать (и, вероятно, более эффективно для больших документов, так как он не злоупотребляет //).

0 голосов
/ 12 апреля 2011

Это преобразование показывает, как найти требуемый минимум и максимум :

<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 select="line">
       <xsl:sort select="field[@id=3]"/>
     </xsl:apply-templates>
 </xsl:template>

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

при применении к предоставленному документу XML :

<document>
    <line id="0">
        <field id="2">X111</field>
        <field id="3">2011-03-31</field>
    </line>
    <line id="1">
        <field id="2">X111</field>
        <field id="3">2011-04-04</field>
    </line>
    <line id="2">
        <field id="2">X111</field>
        <field id="3">2011-04-02</field>
    </line>
    <line id="3">
        <field id="2">X222</field>
        <field id="3">2011-04-04</field>
    </line>
    <line id="4">
        <field id="2">X222</field>
        <field id="3">2011-04-01</field>
    </line>
    <line id="4">
        <field id="2">X333</field>
        <field id="3">2011-04-01</field>
    </line>
</document>

производит :

   Earliest:
   <line id="0">
   <field id="2">X111</field>
   <field id="3">2011-03-31</field>
</line>
   Latest:
   <line id="3">
   <field id="2">X222</field>
   <field id="3">2011-04-04</field>
</line>

Объяснение :

Выбор первого и последнего элемента из отсортированного списка узлов.Даты представлены в «хорошем» формате, поэтому они сортируются как строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...