XSLT: как проверить, все ли определенные узлы равны в одном родителе - PullRequest
4 голосов
/ 06 июля 2010

Я пытаюсь придумать фрагмент кода XSL, который бы проверял, есть ли в классе все ученики с одинаковой фамилией.Это да, тогда (сделать что-нибудь подобное) вывести «все фамилии одинаковые», иначе вывести «все фамилии не совпадают».

Неважно, что печатать.Я просто пытаюсь найти правильную логику для этого.

Вот мой пример XML:

<root>
    <class name="Physics">
        <student>
            <firstname>John</firstname>
            <lastname>Doe</lastname>
            <age>21</age>
        </student>
        <student>
            <firstname>Mary</firstname>
            <lastname>Doe</lastname>
            <age>21</age>
        </student>
        <student>
            <firstname>Ralph</firstname>
            <lastname>Doe</lastname>
            <age>21</age>
        </student>
    </class>
    <class name="Math">
        <student>
            <firstname>John</firstname>
            <lastname>Doe</lastname>
            <age>21</age>
        </student>
        <student>
            <firstname>Mary</firstname>
            <lastname>Doe</lastname>
            <age>21</age>
        </student>
        <student>
            <firstname>Tee</firstname>
            <lastname>Rex</lastname>
            <age>21</age>
        </student>
    </class>
</root>

Следовательно, для класса физики будет выведено «все фамилии одинаковы».А для математического класса это вывело бы «все фамилии не одинаковы».

(Это не мой настоящий XML, потому что он был неприводим к меньшей проблеме, поэтому вместо этого я специально сделал этот XML, чтобы представлять мою проблему)

Любая помощь будет принята с благодарностью.

С уважением, Шобхит

Ответы [ 3 ]

4 голосов
/ 06 июля 2010

Hm. Больше ничего не зная о вашей проблеме, я бы сделал это:

<xsl:template match="class">
  <xsl:choose>
    <xsl:when test="
      count(student[not(lastname = preceding-sibling::student/lastname)]) = 1
    ">
      <xsl:text>all lastnames are same</xsl:text>
    <xsl:when>
    <xsl:otherwise>
      <xsl:text>all lastnames are not same</xsl:text>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

Выражение XPath

student[not(lastname = preceding-sibling::student/lastname)]

выбирает все <student> узлы, чья <lastname> отличается от любой предыдущей фамилии в том же классе.

В классах с одинаковыми фамилиями их количество точно равно 1 (потому что у самого первого ученика всегда есть фамилия, в отличие от любой предыдущей фамилии). Если число превышает 1, то некоторые ученики в этом классе имеют разные фамилии.

Случай, когда в классе вообще нет учеников, будет распознаваться как случай <xsl:otherwise> в приведенной выше логике. Возможно, вы захотите разобраться с этим делом явно каким-то образом.

2 голосов
/ 06 июля 2010

Эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="student"/>
    <xsl:template match="student[1]">all lastnames are same</xsl:template>
    <xsl:template match="student[1][lastname != ../student/lastname]" priority="1">all lastnames are not same</xsl:template>
</xsl:stylesheet>

Результат:

<root>
    <class name="Physics">all lastnames are same</class>
    <class name="Math">all lastnames are not same</class>
</root>

Примечание: Сравнение узлов.

Редактировать : Извините, мисс @ имя.

Редактировать 2 : Компактный.Обратите внимание на @priority, чтобы избежать восстановления после ошибки.

1 голос
/ 07 июля 2010

Это преобразование:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my"
 >
 <xsl:output method="text"/>

 <xsl:key name="kstudentByName"
  match="student" use="lastname"/>

 <my:text>
   <text> not </text>
 </my:text>

 <xsl:variable name="vText" select="document('')/*/my:text/*"/>

 <xsl:template match="/">
  <xsl:variable name="vNumNames" select=
   "count(*/*/student[generate-id()
                     =
                      generate-id(key('kstudentByName', lastname)[1])
                     ]
         )

         > 1
   "/>

   All names are <xsl:value-of select="$vText[$vNumNames]"/> the same.
 </xsl:template>
</xsl:stylesheet>

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

  All names are  not  the same.

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

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