XML / XSL - мюнхенский метод для вложения групп в группы - PullRequest
0 голосов
/ 25 мая 2018

Я работаю над таблицей стилей XSL, где студенты группируются в следующем порядке:

колледж-> уровень-> кафедра-> кафедра-> концентрация-> студент

Таким образом, в основном структура будет "группами внутри групп".Дайте мне знать, если следующее имеет смысл.Дайте мне знать, если вам нужны пояснения!

Это оригинальный XML, который я пытаюсь преобразовать:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<dataroot>
    <student>
        <name_sort>Doe, John</name_sort>
        <name>John Doe</name>
        <level>Undergrad</level>
        <concentration>Studio Art</concentration>
        <college>College 1</college>
        <department>Department 1</department>
       <chair>Chair Name</chair>
    </student>
    <student>
        <name_sort>James, Lisa</name_sort>
        <name>Lisa James</name>
        <level>Undergrad</level>
        <concentration>Studio Art</concentration>
        <college>College 1</college>
        <department>Department 1</department>
       <chair>Chair Name</chair>
    </student>
<dataroot>

Вывод XML с применением таблицы стилей XSL:

<Root>

<!-- Group by College -->

<college>College 1</college>

<!-- Group by Level -->

<level>Undergraduate</level>

<!-- Group by Department -->

<department>Department 1</department>

<!-- Group by Chair -->

<chair>Chair Name</chair>

 <!-- Group by Concentration -->

<concentration>Studio Art</concentration>

<!-- List Students with matching concentration under parent groups -->

<student>
    <name>John Doe</name>
</student>

<student>
    <name>Lisa James</name>
</student>

<!-- Repeat loop -->

</Root>

Это моя попытка, но студенты не группируются правильно.Некоторые студенты, которые «не обучаются», появляются в группе «выпускник», а некоторые группы концентрации дублируются ...

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

<!-- Keys for grouping -->
<xsl:key name="colleges" match="student" use="college"/>
<xsl:key name="levels" match="student" use="level"/>
<xsl:key name="departments" match="student" use="department"/>
<xsl:key name="chairs" match="student" use="chair"/>
<xsl:key name="concentrations" match="student" use="concentration"/>

<xsl:template match="/dataroot">
    <Root>
        <xsl:for-each select="student[generate-id() = generate-id(key('colleges', college)[1])]">
            <xsl:sort select="college" order="ascending"/>

            <xsl:for-each select="key('colleges', college)[generate-id() = generate-id(key('levels', level)[1])]">
                <xsl:sort select="level" order="ascending"/>

                <college><xsl:value-of select="college"/></college>
                <xsl:text>&#xd;</xsl:text>

                <level><xsl:value-of select="level"/> degree recipients</level>
                <xsl:text>&#xd;</xsl:text>

                <xsl:for-each select="key('levels', level)[generate-id() = generate-id(key('departments', department)[1])]">
                    <xsl:sort select="department" order="ascending"/>
                    <department><xsl:value-of select="department"/></department>
                    <xsl:text>&#xd;</xsl:text>

                    <xsl:for-each select="key('departments', department)[generate-id() = generate-id(key('chairs', chair)[1])]">
                        <xsl:sort select="chair" order="ascending"/>
                        <chair><xsl:value-of select="chair"/></chair>
                        <xsl:text>&#xd;</xsl:text>

                        <xsl:for-each select="key('chairs', chair)[generate-id() = generate-id(key('concentrations', concentration)[1])]">
                            <xsl:sort select="concentration" order="ascending"/>
                            <concentration><xsl:value-of select="concentration"/></concentration>
                            <xsl:text>&#xd;</xsl:text>

                            <xsl:for-each select="key('concentrations', concentration)">
                                <xsl:sort select="name_sort" order="ascending"/>
                                <student>
                                    <name><xsl:value-of select="name"/></name>
                                    <xsl:text>&#xd;</xsl:text>
                                </student>
                            </xsl:for-each>
                        </xsl:for-each>
                    </xsl:for-each>
                </xsl:for-each>
            </xsl:for-each>
        </xsl:for-each>
    </Root>
</xsl:template>

Кто-нибудь может мне помочь?

Ответы [ 2 ]

0 голосов
/ 25 мая 2018

Рассмотрите возможность использования одного ключа, который объединяет все необходимые родительские группы.Нет необходимости в нескольких вложенных for:each вызовах.Запустите нужную сортировку внутри <xsl:apply-templates>.Однако вам понадобится элемент контейнера группировки как дочерний для получения прав на случай, если у вас много группировок.Ниже используется <students> с настроенным XML для демонстрации.

XML

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<dataroot>
    <student>
        <name_sort>Doe, John</name_sort>
        <name>John Doe</name>
        <level>Undergrad</level>
        <concentration>Studio Art</concentration>
        <college>College 1</college>
        <department>Department 1</department>
       <chair>Chair Name</chair>
    </student>
    <student>
        <name_sort>James, Lisa</name_sort>
        <name>Lisa James</name>
        <level>Undergrad</level>
        <concentration>Economics</concentration>
        <college>College 1</college>
        <department>Department 1</department>
       <chair>Chair Name</chair>
    </student>
    <student>
        <name_sort>Doe, Jane</name_sort>
        <name>Jane Doe</name>
        <level>Undergrad</level>
        <concentration>Economics</concentration>
        <college>College 1</college>
        <department>Department 1</department>
       <chair>Chair Name</chair>
    </student>
</dataroot>

XSLT

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

  <!-- single key for grouping -->
  <xsl:key name="concatkey" match="student" use="concat(college, level, department, chair, concentration)"/>

  <xsl:template match="/dataroot">
    <root>
      <xsl:apply-templates select="student[generate-id() = generate-id(key('concatkey', 
                                               concat(college, level, department, chair, concentration)))]"/>
    </root>
  </xsl:template>

  <xsl:template match="student">
    <students>
      <xsl:copy-of select="college"/>
      <xsl:copy-of select="level"/>
      <xsl:copy-of select="department"/>
      <xsl:copy-of select="chair"/>
      <xsl:copy-of select="concentration"/>

      <xsl:for-each select="key('concatkey', concat(college, level, department, chair, concentration))">
        <student><xsl:copy-of select="name"/></student>
      </xsl:for-each>
    </students>
  </xsl:template>

 </xsl:stylesheet>

Выход XSLT Fiddle DEMO

<?xml version="1.0" encoding="utf-8"?>
<root>
  <students>
    <college>College 1</college>
    <level>Undergrad</level>
    <department>Department 1</department>
    <chair>Chair Name</chair>
    <concentration>Economics</concentration>
    <student>
      <name>Lisa James</name>
    </student>
    <student>
      <name>Jane Doe</name>
    </student>
  </students>
  <students>
    <college>College 1</college>
    <level>Undergrad</level>
    <department>Department 1</department>
    <chair>Chair Name</chair>
    <concentration>Studio Art</concentration>
    <student>
      <name>John Doe</name>
    </student>
  </students>
</root>
0 голосов
/ 25 мая 2018

С XSLT 2 или 3 легко вложить xsl:for-each-group, как вы пытаетесь с xsl:for-each, но с XSLT 1 и мюнхенской группировкой вам понадобится ключ второго уровня, включающий ключ первого уровня, например,

<xsl:key name="colleges" match="student" use="college"/>
<xsl:key name="levels" match="student" use="concat(college, '|', level)"/>

и используйте, например,

 <xsl:for-each select="key('colleges', college)[generate-id() = generate-id(key('levels', concat(college, '|', level))[1])]">

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

<xsl:key name="departments" match="student" use="concat(department, '|', college, '|', level)"/>

и

 <xsl:for-each select="key('levels', concat(college, '|', level))[generate-id() = generate-id(key('departments', concat(department, '|', college, '|', level))[1])]">

и т. Д.

...