Еще один способ думать об этом - использовать элемент обтекания (.block__item
), который обеспечивает расстояние между элементами с внутренней подкладкой. Эти упаковочные элементы физически расположены рядом друг с другом, но обеспечивают визуальное различие между их содержимым (.block__content
).
Преимущество этого заключается в том, что вам не нужно включать интервал в свои расчеты для ширины или гибкой основы. Если вы хотите изменить интервал, просто обновите padding
.
* Обратите внимание, что вам нужно изменить блочную модель ваших элементов на border-box
, чтобы воспользоваться этим. sup>
* {
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>
Нерекурсивное решение, с помощью ключей:
<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(),'
 ')"/>
</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>
 </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
}
Лучшее решение с ключами, избегая большей части использования оси предыдущего одноуровневого элемента:
Это преобразование:
<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,'
 ')"/>
</xsl:template>
<!-- -->
<xsl:template match="enumValue[@data]">
<xsl:value-of select=
"concat(@name, ' = ', @data,'
 ')"/>
<!-- -->
<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
}
Объяснение:
Ключ называют ksimpleEnValues
индексы все enumValue
элементы, которые не имеют data
атрибут. Индексация сделана генерировать-идентификатором () значение первого предыдущего enumValue
элемент, который имеет a data
атрибут.
Таким образом key('ksimpleEnValues', someId)
набор узлов, содержащий все enumValue
элементы после enumValue
это имеет его генерировать-идентификатор () равный someId
, и все они enumValue
элементы предшествуют следующему enumValue
с a data
атрибут, если такой существует.
ключ ('ksimpleEnValues', '') является набором узлов всех enumValue
элементы, которые не имеют предыдущего enumValue
элемент с a data
атрибут.
Шаблон, который соответствует enumValue
берет дополнительный параметр $pOffset
, в котором значение data
атрибут от непосредственного предыдущего enumValue
элемент с этим атрибутом, будет передан, иначе значение по умолчанию для $pOffset
0.
Сравнение с шаблонами enumValue
элементы, которые имеют a data
атрибут производит свое перечисление значений (@name = @data) и затем применяет шаблоны ко всем enumValue
элементы между собой и следующим (если такой существует), enumValue
с a data
атрибут. Значение data
атрибут передается как $pOffset
параметр и это будут добавлены к относительному положению каждого выбранного enumValue
элемент при создании вывода из его обработки.
Вы не можете заменить "переменные" в 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>