Как эмулировать перечисление C в XSLT с дополнительными значениями

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

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

* Обратите внимание, что вам нужно изменить блочную модель ваших элементов на border-box, чтобы воспользоваться этим.

[ 1113]
* {
  box-sizing: border-box;
}

.block {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  max-width: 900px;
  border: 1px solid lightgrey;
  padding: 2px;
}

.block__item {
  flex: 0 1 calc(100% / 3);
  padding: 2px;
}

.block__content {
  height: 20px;
  background-color: grey;
  color: white;
  font-size: 10px;
  font-weight: 700;
  line-height: 20px;
  text-align: center;
}

@media (max-width: 400px) {
  .block__item {
    flex-basis: 50%;
  }
}
<div class="block">
  <div class="block__item">
    <div class="block__content">1</div>
  </div>
  <div class="block__item">
    <div class="block__content">2</div>
  </div>
  <div class="block__item">
    <div class="block__content">3</div>
  </div>
  <div class="block__item">
    <div class="block__content">4</div>
  </div>
  <div class="block__item">
    <div class="block__content">5</div>
  </div>
</div>

5
задан 2 revs 11 February 2009 в 10:09
поделиться

3 ответа

Нерекурсивное решение, с помощью ключей:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:strip-space elements="*"/>
 <xsl:output method="text"/>

 <xsl:key name="koffsetEnums" match="enumValue[@data]"
  use="generate-id()"/>

    <xsl:template match="enum">
      enum <xsl:value-of select="@name"/> {
      <xsl:apply-templates select="enumValue"/>
      }
    </xsl:template>

    <xsl:template match="enumValue">
      <xsl:value-of select="concat(@name, ' = ')"/>

      <xsl:variable name="voffsetValueId" select=
       "generate-id((. | preceding-sibling::enumValue)
                                            [@data][last()]
                  )"/>

      <xsl:choose>
        <xsl:when test="not($voffsetValueId)">
          <xsl:value-of select="concat(position(),'&#xA;      ')"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:variable name="vinitOffset" select=
           "key('koffsetEnums', $voffsetValueId)/@data"
           />

           <xsl:value-of select=
            "$vinitOffset
            +
               count(preceding-sibling::enumValue)
             -
               count(key('koffsetEnums', $voffsetValueId)/preceding-sibling::enumValue)
            "
            />
           <xsl:text>&#xA;      </xsl:text>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

Когда вышеупомянутое преобразование применяется на первоначально предоставленный XML-документ:

<enum name="anenum">
    <enumValue name="a"/>
    <enumValue name="b"/>
    <enumValue name="c" data="10"/>
    <enumValue name="d" />
    <enumValue name="e" />
</enum>

к необходимому результату приводят:

enum anenum {
      a = 1
      b = 2
      c = 10
      d = 11
      e = 12

      }
4
ответ дан 14 December 2019 в 09:01
поделиться

Лучшее решение с ключами, избегая большей части использования оси предыдущего одноуровневого элемента:

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

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:output method="text"/>
<!--                                              -->   
    <xsl:key name="ksimpleEnValues" match="enumValue[not(@data)]"
     use="generate-id(preceding-sibling::enumValue[@data][1])"/>
<!--                                              -->       
    <xsl:template match="enum">
    enum <xsl:value-of select="@name"/>
         {      
          <xsl:apply-templates select=
           "key('ksimpleEnValues', '')
           "/>
           <xsl:apply-templates select="enumValue[@data]"/>
         }
    </xsl:template>
<!--                                              -->
    <xsl:template match="enumValue">
      <xsl:param name="pOffset" select="0"/>
        <xsl:value-of select=
         "concat(@name, ' = ', position()+$pOffset,'&#xA;      ')"/>
    </xsl:template>
<!--                                              -->
    <xsl:template match="enumValue[@data]">
        <xsl:value-of select=
         "concat(@name, ' = ', @data,'&#xA;      ')"/>
<!--                                              -->
      <xsl:apply-templates select=
           "key('ksimpleEnValues', generate-id())">
       <xsl:with-param name="pOffset" select="@data"/>
      </xsl:apply-templates>
  </xsl:template>       
</xsl:stylesheet>

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

<enum name="anenum">
    <enumValue name="a"/>
    <enumValue name="b"/>
    <enumValue name="c" data="10"/>
    <enumValue name="d" />
    <enumValue name="e" />
</enum>

Приводит к требуемому результату:

enum anenum
 {      
  a = 1
  b = 2
  c = 10
  d = 11
  e = 12
 }

Объяснение:

  1. Ключ называют ksimpleEnValues индексы все enumValue элементы, которые не имеют data атрибут. Индексация сделана генерировать-идентификатором () значение первого предыдущего enumValue элемент, который имеет a data атрибут.

  2. Таким образом key('ksimpleEnValues', someId) набор узлов, содержащий все enumValue элементы после enumValue это имеет его генерировать-идентификатор () равный someId, и все они enumValue элементы предшествуют следующему enumValue с a data атрибут, если такой существует.

  3. ключ ('ksimpleEnValues', '') является набором узлов всех enumValue элементы, которые не имеют предыдущего enumValue элемент с a data атрибут.

  4. Шаблон, который соответствует enumValue берет дополнительный параметр $pOffset, в котором значение data атрибут от непосредственного предыдущего enumValue элемент с этим атрибутом, будет передан, иначе значение по умолчанию для $pOffset 0.

  5. Сравнение с шаблонами enumValue элементы, которые имеют a data атрибут производит свое перечисление значений (@name = @data) и затем применяет шаблоны ко всем enumValue элементы между собой и следующим (если такой существует), enumValue с a data атрибут. Значение data атрибут передается как $pOffset параметр и это будут добавлены к относительному положению каждого выбранного enumValue элемент при создании вывода из его обработки.

2
ответ дан 14 December 2019 в 09:01
поделиться

Вы не можете заменить "переменные" в xsl, но можно использовать рекурсию. Не используйте предикаты предыдущего одноуровневого элемента, если не абсолютно срочный, поскольку они уничтожат Вашу производительность.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:template match="/" >
        <xsl:call-template name="printEnum">
            <xsl:with-param name="value" select="0"/>
            <xsl:with-param name="position" select="1"/>
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="printEnum">
        <xsl:param name="position"/>    
        <xsl:param name="value" select="0"/>
        <xsl:variable name="node" select="/enum/enumValue[$position]"/>
        <xsl:variable name="enumValue">
            <xsl:choose>
                <xsl:when test="$node/@data">
                    <xsl:value-of select="$node/@data"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$value + 1"/>
                </xsl:otherwise>
            </xsl:choose>       
        </xsl:variable>     
        <xsl:value-of select="concat($node/@name, ' = ', $enumValue, ' , ')"/>
        <xsl:if test="/enum/enumValue[$position + 1]">
            <xsl:call-template name="printEnum">
                <xsl:with-param name="value" select="$enumValue"/>
                <xsl:with-param name="position" select="$position + 1"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>
1
ответ дан 14 December 2019 в 09:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: