Я обычно пишу шаблон, соответствующий тем элементам, которые отображаются в линию, и выбираю другие значения по мере необходимости с помощью навигации XPath:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:apply-templates select="//availability/stock"/>
</xsl:template>
<xsl:template match="stock">
<xsl:value-of select="ancestor::market/category/type, ancestor::element!(name, type, color), @cat, @in" separator=", "/>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
Это позволяет получить компактную и четкую запись о том, какие значения составляют строку в файле CSV.
https://xsltfiddle.liberty -development.net / jyH9rM9
Статическая информация заголовка, такая как category/type
, также может храниться в глобальной переменной:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:output method="text"/>
<xsl:variable name="category-type" select="market/category/type"/>
<xsl:template match="/">
<xsl:apply-templates select="//availability/stock"/>
</xsl:template>
<xsl:template match="stock">
<xsl:value-of select="$category-type, ancestor::element!(name, type, color), @cat, @in" separator=", "/>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty -development.net / jyH9rM9 / 1
Третий способ в XSLT 3 - это сбор значений декларативным способом с использованием аккумуляторов:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="3.0">
<xsl:mode use-accumulators="#all"/>
<xsl:output method="text"/>
<xsl:accumulator name="cat-type" as="xs:string?" initial-value="()">
<xsl:accumulator-rule match="market/category/type" select="string()"/>
</xsl:accumulator>
<xsl:accumulator name="element-name" as="xs:string?" initial-value="()">
<xsl:accumulator-rule match="item/element" select="()"/>
<xsl:accumulator-rule match="items/element/name" select="string()"/>
</xsl:accumulator>
<xsl:accumulator name="element-type" as="xs:string?" initial-value="()">
<xsl:accumulator-rule match="item/element" select="()"/>
<xsl:accumulator-rule match="items/element/type" select="string()"/>
</xsl:accumulator>
<xsl:accumulator name="element-color" as="xs:string?" initial-value="()">
<xsl:accumulator-rule match="item/element" select="()"/>
<xsl:accumulator-rule match="items/element/color" select="string()"/>
</xsl:accumulator>
<xsl:template match="/">
<xsl:apply-templates select="//availability/stock"/>
</xsl:template>
<xsl:template match="stock">
<xsl:value-of select="accumulator-before('cat-type'), accumulator-before('element-name'), accumulator-before('element-type'), accumulator-before('element-color'), @cat, @in" separator=", "/>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty -development.net / jyH9rM9 / 2
Это имеет то преимущество, что вы можете адаптировать его к потоковой передаче с некоторыми изменениями, так как вы можете преобразовывать огромные входные данные с помощью Saxon 9.8 EE, не сохраняя полное дерево ввода XML в памяти:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="3.0">
<xsl:mode use-accumulators="#all" />
<xsl:output method="text"/>
<xsl:accumulator name="cat-type" as="xs:string?" initial-value="()" streamable="yes">
<xsl:accumulator-rule match="market/category/type/text()" select="string()"/>
</xsl:accumulator>
<xsl:accumulator name="element-name" as="xs:string?" initial-value="()" streamable="yes">
<xsl:accumulator-rule match="item/element" select="()"/>
<xsl:accumulator-rule match="items/element/name/text()" select="string()"/>
</xsl:accumulator>
<xsl:accumulator name="element-type" as="xs:string?" initial-value="()" streamable="yes">
<xsl:accumulator-rule match="item/element" select="()"/>
<xsl:accumulator-rule match="items/element/type/text()" select="string()"/>
</xsl:accumulator>
<xsl:accumulator name="element-color" as="xs:string?" initial-value="()" streamable="yes">
<xsl:accumulator-rule match="item/element" select="()"/>
<xsl:accumulator-rule match="items/element/color/text()" select="string()"/>
</xsl:accumulator>
<xsl:template match="/">
<xsl:apply-templates select="outermost(//availability/stock)"/>
</xsl:template>
<xsl:template match="stock">
<xsl:value-of select="accumulator-before('cat-type'), accumulator-before('element-name'), accumulator-before('element-type'), accumulator-before('element-color'), @cat, @in" separator=", "/>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>