Атрибуты отсутствуют после сортировки элементов - PullRequest
2 голосов
/ 03 ноября 2011

Мне нужно создать таблицу стилей XSLT 2.0, которая обрабатывает полную периодическую таблицу , сортирует атомы (только их имена) по группам на основе их состояния (то есть атрибут STATE элемента ATOM) в текстовый файл.

Я что-то сделал, но есть элементы <ATOM> без атрибутов STATE.Эти элементы также должны присутствовать в итоговом документе.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:template match="PERIODIC_TABLE">
      <xsl:for-each-group select="ATOM" group-by="@STATE" >
        <xsl:text> **    </xsl:text>
        <xsl:value-of select="current-grouping-key()"/>
        <xsl:text>
</xsl:text>
        <xsl:for-each select="current-group()">
          <xsl:sort select="NAME"/>
          <xsl:value-of select="NAME"/>
          <xsl:text>
</xsl:text>
        </xsl:for-each>
        <xsl:text>
</xsl:text>
      </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

Ответы [ 2 ]

2 голосов
/ 04 ноября 2011

Я лишь слегка коснулся вашего кода, внеся следующие изменения :

Заменить:

group-by="@STATE"

с:

group-by="(@STATE, 'UNKNOWN')[1]"

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

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
    <xsl:template match="PERIODIC_TABLE">
      <xsl:for-each-group select="ATOM"
        group-by="(@STATE, 'UNKNOWN')[1]" >
        <xsl:text> **    </xsl:text>
        <xsl:value-of select="current-grouping-key()"/>
        <xsl:text>
</xsl:text>
        <xsl:for-each select="current-group()">
          <xsl:sort select="NAME"/>
          <xsl:value-of select="NAME"/>
          <xsl:text>
</xsl:text>
        </xsl:for-each>
        <xsl:text>
</xsl:text>
      </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

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

 **    UNKNOWN
Actinium
Aluminum
Americium
Antimony
Arsenic
Astatine
Barium
Berkelium
Beryllium
Bohrium
Boron
Bromine
Cadmium
Calcium
Californium
Cerium
Cesium
Chlorine
Chromium
Cobalt
Copper
Curium
Dubnium
Dysprosium
Einsteinium
Erbium
Europium
Fermium
Fluorine
Francium
Gadolinium
Gallium
Germanium
Hafnium
Hassium
Holmium
Indium
Iodine
Iridium
Iron
Krypton
Lanthanum
Lawrencium
Lead
Lithium
Lutetium
Magnesium
Manganese
Meitnerium
Mendelevium
Mercury
Molybdenum
Neodymium
Neon
Neptunium
Nickel
Niobium
Nitrogen
Nobelium
Osmium
Oxygen
Palladium
Phosphorus
Platinum
Plutonium
Polonium
Potassium
Praseodymium
Promethium
Protactinium
Radium
Radon
Rhenium
Rhodium
Rubidium
Ruthenium
Rutherfordium
Samarium
Scandium
Seaborgium
Selenium
Silicon
Silver
Sodium
Strontium
Sulfur
Tantalum
Technetium
Tellurium
Terbium
Thallium
Thorium
Thulium
Tin
Titanium
Tungsten
Uranium
Vanadium
Ytterbium
Yttrium
Zinc
Zirconium
ununbium
ununnilium
unununium

 **    GAS
Argon
Helium
Hydrogen
Xenon

 **    SOLID
Bismuth
Carbon
Gold
1 голос
/ 04 ноября 2011

Вы можете просто сделать xsl:for-each для всех ATOM, которые не имеют атрибута STATE.Вы можете разделить это с чем-то вроде «OTHER».

Эта измененная версия вашей таблицы стилей:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:template match="PERIODIC_TABLE">
    <xsl:for-each-group select="ATOM" group-by="@STATE">
      <xsl:text> **    </xsl:text>
      <xsl:value-of select="current-grouping-key()"/>
      <xsl:text>&#xA;</xsl:text>
      <xsl:for-each select="current-group()">
        <xsl:sort select="NAME" case-order="#default"/>
        <xsl:value-of select="NAME"/>
        <xsl:text>&#xA;</xsl:text>
      </xsl:for-each>
      <xsl:text>&#xA;</xsl:text>
    </xsl:for-each-group>
    <xsl:if test="ATOM[not(@STATE)]">
      <xsl:text> **    OTHER&#xA;</xsl:text>
      <xsl:for-each select="ATOM[not(@STATE)]">
        <xsl:sort select="NAME" case-order="#default"/>
        <xsl:value-of select="NAME"/>
        <xsl:text>&#xA;</xsl:text>      
      </xsl:for-each>      
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

производит следующий вывод (во всей своей красе):

 **    GAS
Argon
Helium
Hydrogen
Xenon

 **    SOLID
Bismuth
Carbon
Gold

 **    OTHER
Actinium
Aluminum
Americium
Antimony
Arsenic
Astatine
Barium
Berkelium
Beryllium
Bohrium
Boron
Bromine
Cadmium
Calcium
Californium
Cerium
Cesium
Chlorine
Chromium
Cobalt
Copper
Curium
Dubnium
Dysprosium
Einsteinium
Erbium
Europium
Fermium
Fluorine
Francium
Gadolinium
Gallium
Germanium
Hafnium
Hassium
Holmium
Indium
Iodine
Iridium
Iron
Krypton
Lanthanum
Lawrencium
Lead
Lithium
Lutetium
Magnesium
Manganese
Meitnerium
Mendelevium
Mercury
Molybdenum
Neodymium
Neon
Neptunium
Nickel
Niobium
Nitrogen
Nobelium
Osmium
Oxygen
Palladium
Phosphorus
Platinum
Plutonium
Polonium
Potassium
Praseodymium
Promethium
Protactinium
Radium
Radon
Rhenium
Rhodium
Rubidium
Ruthenium
Rutherfordium
Samarium
Scandium
Seaborgium
Selenium
Silicon
Silver
Sodium
Strontium
Sulfur
Tantalum
Technetium
Tellurium
Terbium
Thallium
Thorium
Thulium
Tin
Titanium
Tungsten
ununbium
ununnilium
unununium
Uranium
Vanadium
Ytterbium
Yttrium
Zinc
Zirconium

Несколько других вещей, которые я сделал, это добавили атрибуты case-order к элементам xsl:sort, и я использовал &#xA; шестнадцатеричную ссылку на сущность для перевода строки.здесь можно использовать concat() вместо отдельного xsl:text для новых строк / пробелов.

Вместо этого:

<xsl:value-of select="NAME"/>
<xsl:text>&#xA;</xsl:text>

вы можете сделать это:

<xsl:value-of select="concat(NAME,'&#xA;')"/>
...