У меня есть XML-файл:Как улучшить XSLT-эффективность
Я думаю, вы могли бы понять мой XML как таблицу содержимого.
AElement @Name='1'
является запись
Первый AElement @Name='2'
будет запись 1.1
AElement @Name='3'
ниже этого AElement @Name='2'
бы непосредственно принадлежат ему делать им доступ 1.1.1, вход 1.1.2 и вступление 1.1 .3 и ввод 1.1.4
Второй AElement @Name='2'
будет запись 1.2
и так далее ..
<ROOT>
<AElement Name="1">
<AElement>
<Child1></Child1>
<Child2>0000</Child2>
</AElement>
</AElement>
<AElement Name="2">
<AElement>
<Child1>E</Child1>
<Child2>1000</Child2>
</AElement>
</AElement>
<AElement Name="3">
<AElement>
<Child1>E</Child1>
<Child2>0100</Child2>
</AElement>
</AElement>
<AElement Name="3">
<AElement>
<Child1>U</Child1>
<Child2>0200</Child2>
</AElement>
</AElement>
<AElement Name="3">
<AElement>
<Child1>E</Child1>
<Child2>0300</Child2>
</AElement>
</AElement>
<AElement Name="2">
<AElement>
<Child1>E</Child1>
<Child2>2000</Child2>
</AElement>
</AElement>
<AElement Name="3">
<AElement>
<Child1>N</Child1>
<Child2>0400</Child2>
</AElement>
</AElement>
<AElement Name="3">
<AElement>
<Child1>E</Child1>
<Child2>0500</Child2>
</AElement>
</AElement>
<AElement Name="2">
<AElement>
<Child1>E</Child1>
<Child2>3000</Child2>
</AElement>
</AElement>
<AElement Name="2">
<AElement>
<Child1>U</Child1>
<Child2>4000</Child2>
</AElement>
</AElement>
<AElement Name="3">
<AElement>
<Child1>E</Child1>
<Child2>0600</Child2>
</AElement>
</AElement>
<AElement Name="4">
<AElement>
<Child1>E</Child1>
<Child2>0010</Child2>
</AElement>
</AElement>
</ROOT>
Wanted результат:
Для каждого AElement
таблица должна быть создана
где для каждого AElement
следующего шага
если AElement/Child1='E'
этого AElement
необходимо создать таблицу-строку и таблицу-таблицу.
Эта таблица-ячейка должна быть заполнена значением AElement/Child2
AElement
.
Однако эта таблица должна быть создана только в том случае, если существует AElement
следующего этапа с AElement/Child1='E'
.
ПРИМЕР
Для каждого AElement @Name='2'
таблица должна быть создана , где для каждого AElement @Name='3'
, который принадлежит AElement @Name='2'
, если AElement/Child1='E'
из AElement @Name='3'
таблица-строки и таблицы-ячейка должна быть создана этого таблицы- ячейка должна быть заполнена значением AElement/Child2
этого AElement @Name='3'
.
Так что:
<AElement Name="2">
<AElement>
<Child1>U</Child1>
<Child2>4000</Child2>
</AElement>
</AElement>
<AElement Name="3">
<AElement>
<Child1>E</Child1>
<Child2>0600</Child2>
</AElement>
</AElement>
<AElement Name="4">
<AElement>
<Child1>E</Child1>
<Child2>0010</Child2>
</AElement>
</AElement>
становится этим:
<fo:block>STEP 2 4000</fo:block>
<fo:table>
<fo:table-row>
<fo:table-cell>
<fo:block>
0600
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table>
НО это:
<AElement Name="2">
<AElement>
<Child1>E</Child1>
<Child2>3000</Child2>
</AElement>
</AElement>
<AElement Name="2">
<AElement>
<Child1>U</Child1>
<Child2>4000</Child2>
</AElement>
</AElement>
не будет создавать таблицу, поскольку STEP 3000 не имеет следующие AElements @Name='3'
.
<fo:root>
<fo:block>STEP 1 0000</fo:block>
<fo:table>
<fo:table-row>
<fo:table-cell>
<fo:block>
1000
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>
2000
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>
3000
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table>
<fo:block>STEP 2 1000</fo:block>
<fo:table>
<fo:table-row>
<fo:table-cell>
<fo:block>
0100
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>
0300
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table>
<fo:block>STEP 2 2000</fo:block>
<fo:table>
<fo:table-row>
<fo:table-cell>
<fo:block>
0500
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table>
<fo:block>STEP 2 4000</fo:block>
<fo:table>
<fo:table-row>
<fo:table-cell>
<fo:block>
0600
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table>
<fo:block>STEP 3 0600</fo:block>
<fo:table>
<fo:table-row>
<fo:table-cell>
<fo:block>
0010
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table>
</fo:root>
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
>
<xsl:output indent="yes" />
<!-- all <AElement> we consider for output, indexed by their @Name and group ID -->
<xsl:key name="AElementGroup1" match="AElement[AElement/Child1 = 'E']" use="
concat(@Name, '|', generate-id(preceding-sibling::AElement[@Name = '1'][1]))
" />
<xsl:key name="AElementGroup2" match="AElement[AElement/Child1 = 'E']" use="
concat(@Name, '|', generate-id(preceding-sibling::AElement[@Name = '2'][1]))
" />
<xsl:key name="AElementGroup3" match="AElement[AElement/Child1 = 'E']" use="
concat(@Name, '|', generate-id(preceding-sibling::AElement[@Name = '3'][1]))
" />
<xsl:key name="AElementGroup4" match="AElement[AElement/Child1 = 'E']" use="
concat(@Name, '|', generate-id(preceding-sibling::AElement[@Name = '4'][1]))
" />
<xsl:key name="AElementGroup5" match="AElement[AElement/Child1 = 'E']" use="
concat(@Name, '|', generate-id(preceding-sibling::AElement[@Name = '5'][1]))
" />
<xsl:key name="AElementGroup6" match="AElement[AElement/Child1 = 'E']" use="
concat(@Name, '|', generate-id(preceding-sibling::AElement[@Name = '6'][1]))
" />
<xsl:key name="AElementGroup7" match="AElement[AElement/Child1 = 'E']" use="
concat(@Name, '|', generate-id(preceding-sibling::AElement[@Name = '7'][1]))
" />
<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master
master-name="DIN-A4-Landscape"
page-height="210mm"
page-width="297mm"
margin-left="1mm"
margin-right="1mm"
margin-top="1mm"
margin-bottom="1mm"
>
<fo:region-body margin="1mm"/>
<fo:region-before region-name="header" extent="5mm"/>
<fo:region-after region-name="footer" extent="15mm"/>
<fo:region-start region-name="left" extent="5mm"/>
<fo:region-end region-name="right" extent="5mm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="DIN-A4-Landscape">
<fo:flow flow-name="xsl-region-body">
<xsl:call-template name="ink">
<xsl:with-param name="Now" select="1"/>
</xsl:call-template>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template name="ink">
<xsl:param name="Now"/>
<xsl:param name="Next" select="$Now + 1"/>
<xsl:param name="Ende" select="3"/>
<xsl:apply-templates select="ROOT">
<xsl:with-param name="nowStep" select="$Now"/>
<xsl:with-param name="nextStep" select="$Next"/>
</xsl:call-template>
<xsl:if test="$Ende > $Now">
<xsl:call-template name="ink">
<xsl:with-param name="Now" select="$Now + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="ROOT">
<xsl:param name="nowStep"/>
<xsl:param name="nextStep"/>
<xsl:for-each select="AElement[@Name = $nowStep]">
<xsl:variable name="groupId" select="generate-id()" />
<xsl:variable name="groupKey" select="concat($nextStep, '|', $groupId)" />
<fo:block><xsl:value-of select="concat('STEP ' , $nowStep)" /></fo:block>
<xsl:variable name="group">
<xsl:value-of select="concat('InternalElementGroup',$nowStep)"/>
</xsl:variable>
<xsl:if test="count(key($group, $groupKey))>=1">
<fo:table page-break-after="always">
<fo:table-body>
<xsl:choose>
<xsl:when test="$nowStep = 1">
<xsl:apply-templates select="key('AElementGroup1', $groupKey)/AElement" />
</xsl:when>
<xsl:when test="$nowStep = 2">
<xsl:apply-templates select="key('AElementGroup2', $groupKey)/AElement" />
</xsl:when>
<xsl:when test="$nowStep = 3">
<xsl:apply-templates select="key('AElementGroup3', $groupKey)/AElement" />
</xsl:when>
</xsl:choose>
</fo:table-body>
</fo:table>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="AElement/AElement">
<fo:table-row>
<fo:table-cell>
<fo:block><xsl:value-of select="Child2"/></fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:template>
</xsl:transform>
Этот код по @Tomalak возвращает желаемый результат.
Да, 'count (previous-sibling' очень медленно. В C# я бы использовал Linq для Xml вместо XSLT. –