xslt следующая группа - PullRequest
       1

xslt следующая группа

2 голосов
/ 19 августа 2011

Старый исходный XML:

<Employees>
    <Person>
      <FirstName>Joy</FirstName>
      <IsManager>N</IsManager>
    </Person>
    <Person>
      <FirstName>Joyce</FirstName>
      <IsManager>N</IsManager>
    </Person>
    <Person>
      <FirstName>Joe</FirstName>
      <IsManager>Y</IsManager>
    </Person>...
</Employees>

Новый исходный XML:

<Employees>
        <Person>
        <FirstName>Joy</FirstName>
        <DetailsArray>
            <Details1>
            <IsManager>N</IsManager>
            <IsSuperviser>N</IsSuperviser>
            </Details1>
        <Details2>
                <IsManager>N</IsManager>
            <IsSuperviser>N</IsSuperviser>
            </Details2>
        </DetailsArray>
        </Person>
        <Person>
        <FirstName>Joyce</FirstName>
        <DetailsArray>
            <Details1>
            <IsManager>N</IsManager>
            <IsSuperviser>N</IsSuperviser>
            </Details1>
        <Details2>
                <IsManager>N</IsManager>
            <IsSuperviser>N</IsSuperviser>
            </Details2>
        </DetailsArray>
        </Person>
        <Person>
        <FirstName>Joe</FirstName>
        <DetailsArray>
            <Details1>
            <IsManager>N</IsManager>
            <IsSuperviser>N</IsSuperviser>
            </Details1>
        <Details2>
                <IsManager>Y</IsManager>
            <IsSuperviser>N</IsSuperviser>
            </Details2>
    </DetailsArray>
        </Person>...
</Employees>

вывод должен быть:

    <Names>
    <Name num='1'>Joe</Name>
    <Name num='2'>Joy</Name>
    <Name num='3'>Joyce</Name>
    ....
    </Names>

Этот исходный XML имеет некоторые корректировки по сравнению с предыдущим XML. Здесь новое условие «Человек может быть связан с 2проектами или 2задачами», так что мне нужно, чтобы вывод начался с человека с IsManager = 'Y', даже если IsManager равен 'y' в теге Details2 в DetailsArray. Вывод не должен иметь дубликатов имен. Предположим, если мы отсортируем имена будут дублированы ..

Спасибо за предыдущие ответы ..

Ответы [ 3 ]

2 голосов
/ 19 августа 2011

EDIT . Как указывает lwburk, исходное решение этого ответа просто сортирует узлы по IsManager.

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

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="Employees">

    <xsl:variable name="position" select="count(Person) - count(Person/IsManager[. = 'Y'][1]/../following-sibling::*)" />

    <xsl:call-template name="person">
        <xsl:with-param name="name" select="Person/IsManager[. = 'Y'][1]/../FirstName" />
        <xsl:with-param name="position" select="'1'" />
    </xsl:call-template>

    <xsl:for-each select="Person[position() &gt; $position]">            
            <xsl:call-template name="person" />
    </xsl:for-each>

    <xsl:for-each select="Person[position() &lt; $position]">
            <xsl:call-template name="person" />
    </xsl:for-each>
</xsl:template>

<xsl:template name="person">
    <xsl:param name="name" select="FirstName" />
    <xsl:param name="position" select="position() + 1" />   

    <Name>
        <xsl:attribute name="num"><xsl:value-of select="$position" /></xsl:attribute>
        <xsl:value-of select="$name" />
    </Name>
</xsl:template>

</xsl:stylesheet>

Старый ответ .

Я не уверен в вашем вопросе, но я думаю, что вы хотите получить все имена, начиная с человека с IsManager = Y. Вы можете использовать <xsl:sort> по значению IsManager. Не забудьте указать «по убыванию» в атрибуте «порядок» (иначе, человек с IsManager = Y будет последним).

Я написал пример, который работает с вашими входными данными:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="Employees">
    <xsl:for-each select="Person">
        <xsl:sort select="IsManager" order="descending" />

            <Name>
                <xsl:attribute name="num">
                    <xsl:value-of select="position()" />
                </xsl:attribute>
                <xsl:value-of select="FirstName" />

            </Name>

    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>
1 голос
/ 20 августа 2011

Это короткое и простое преобразование (без режимов, без переменных и только три шаблона):

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

 <xsl:template match="/">
  <Names>
    <xsl:apply-templates select="*/Person[IsManager='Y'][1]"/>
  </Names>
 </xsl:template>    

 <xsl:template match="Person[IsManager='Y']">
  <xsl:apply-templates select=
   "FirstName |../Person[not(generate-id()=generate-id(current()))]
                /FirstName
   ">
   <xsl:sort select=
    "generate-id(..) = generate-id(/*/*[IsManager = 'Y'][1])"
   order="descending"/>
   <xsl:sort select=
     "boolean(../preceding-sibling::Person[IsManager='Y'])"
     order="descending"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="FirstName">
  <Name num="{position()}"><xsl:value-of select="."/></Name>
 </xsl:template>
</xsl:stylesheet>

при применении к следующему XML (то же, что предоставлено @lwburk):

<Employees>
    <Person>
        <FirstName>Joy</FirstName>
        <IsManager>N</IsManager>
    </Person>
    <Person>
        <FirstName>Joyce</FirstName>
        <IsManager>N</IsManager>
    </Person>
    <Person>
        <FirstName>Joe</FirstName>
        <IsManager>Y</IsManager>
    </Person>
    <Person>
        <FirstName>Professor X</FirstName>
        <IsManager>N</IsManager>
    </Person>
    <Person>
        <FirstName>Songey</FirstName>
        <IsManager>Y</IsManager>
    </Person>
</Employees>

дает желаемый, правильный результат :

<Names>
   <Name num="1">Joe</Name>
   <Name num="2">Professor X</Name>
   <Name num="3">Songey</Name>
   <Name num="4">Joy</Name>
   <Name num="5">Joyce</Name>
</Names>

Объяснение :

  1. Это типичный случай сортировки с использованием нескольких ключей.

  2. Критерий сортировки с наивысшим приоритетом - является ли родительский родитель первым руководителем.

  3. Вторым критерием сортировки приоритета является то, следует ли родительское лицо за менеджером.

  4. Мы используем тот факт, что при сортировке логических значений false() предшествует true(), поэтому мы обрабатываем отсортированный список узлов в порядке убывания.

0 голосов
/ 19 августа 2011

Звучит так, будто вы пытаетесь начать с первого менеджера, а затем обрабатывает все элементы Person по порядку, возвращаясь к началу, чтобы получить все элементы перед элементом partition.

Следующая таблица стилей достигает желаемого результата:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:apply-templates select="Employees/Person"/>
    </xsl:template>
    <xsl:template match="Person[IsManager='Y'][1]">
        <Name num="1">
            <xsl:apply-templates select="FirstName"/>
        </Name>
        <!--  partition -->
        <xsl:apply-templates select="following-sibling::Person" mode="after"/>
        <xsl:apply-templates select="../Person" mode="before">
            <xsl:with-param name="pos" select="last() - position() + 1"/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="Person" mode="after">
        <Name num="{position() + 1}">
            <xsl:apply-templates select="FirstName"/>
        </Name>
    </xsl:template>
    <xsl:template match="Person[not(IsManager='Y') and 
              not(preceding-sibling::Person[IsManager='Y'])]" mode="before">
        <xsl:param name="pos" select="0"/>
        <Name num="{position() + $pos}">
            <xsl:apply-templates select="FirstName"/>
        </Name>
    </xsl:template>
    <xsl:template match="Person"/>
    <xsl:template match="Person" mode="before"/>
</xsl:stylesheet>

Примечание: 1) Для этого решения требуется наличие хотя бы одного менеджера в источнике; 2) Это может быть не очень эффективным решением, так как требует нескольких проходов и использует preceding-sibling для проверки членства в группе (для элементов перед элементом partition).

Пример ввода:

<Employees>
    <Person>
        <FirstName>Joy</FirstName>
        <IsManager>N</IsManager>
    </Person>
    <Person>
        <FirstName>Joyce</FirstName>
        <IsManager>N</IsManager>
    </Person>
    <Person>
        <FirstName>Joe</FirstName>
        <IsManager>Y</IsManager>
    </Person>
    <Person>
        <FirstName>Professor X</FirstName>
        <IsManager>N</IsManager>
    </Person>
    <Person>
        <FirstName>Songey</FirstName>
        <IsManager>Y</IsManager>
    </Person>
</Employees>

Выход:

<Name num="1">Joe</Name>
<Name num="2">Professor X</Name>
<Name num="3">Songey</Name>
<Name num="4">Joy</Name>
<Name num="5">Joyce</Name>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...