Reputation: 1127
I have input xml file about structure:
<TabularXml>
<Sheet>
<Row id="2">
<Cell id="1" name="A" type="String">aaa</Cell>
<Cell id="2" name="B" type="String">1</Cell>
</Row>
<Row id="3">
<Cell id="1" name="A" type="String">aaa</Cell>
<Cell id="2" name="B" type="String">2</Cell>
</Row>
<Row id="3">
<Cell id="1" name="A" type="String">bbb</Cell>
<Cell id="2" name="B" type="String">3</Cell>
</Row>
<Row id="4">
<Cell id="1" name="A" type="String">ccc</Cell>
<Cell id="2" name="B" type="String">4</Cell>
</Row>
</Sheet>
</TabularXml>
And I want output:
<Beholdninger>
<Unique>3</Unique>
<AllePoster>
<A>aaa</A>
<p><B>1<B/></p>
<p><B>2<B/></p>
<A>bbb</A>
<p><B>3<B/></p>
<A>ccc</A>
<p><B>4<B/></p>
</AllePoster>
</Beholdninger>
My current xslt code:
</msxsl:script>
<xsl:key name="product" match="//Row/Cell[@name = 'A']/text()" use="." />
<xsl:template match="Sheet">
<Beholdninger>
<xsl:for-each select="//Row/Cell[@name = 'A']/text()[generate-id() = generate-id(key('product',.)[1])]">
<xsl:if test="position()=last()">
<Unique><xsl:value-of select="last()"/></Unique>
</xsl:if>
</xsl:for-each>
<AllePoster>
<xsl:for-each select="//Row/Cell[@name = 'A']/text()[generate-id() = generate-id(key('product',.)[1])]">
<A><xsl:value-of select="."/></A>
<xsl:for-each select="key('product',.)">
<xsl:variable select="position()" name='x'/>
<p><B><xsl:value-of select="//Row[@id = $x]/Cell[@name = 'B']"/></B></p>
</xsl:for-each>
</xsl:for-each>
</AllePoster>
</Beholdninger>
</xsl:template>
</xsl:stylesheet>
Where I getting:
<Beholdninger>
<Unique>3</Unique>
<AllePoster>
<A>aaa</A>
<p><B>1<B/></p>
<p><B>2<B/></p>
<A>bbb</A>
<p><B>1<B/></p>
<A>ccc</A>
<p><B>1<B/></p>
</AllePoster>
</Beholdninger>
This is because the position()
function generates indexes from the beginning of each unique <A>
, not based on indexes from the entire input file. How can this be solved? Or maybe I need to rewrite the script from the beginning and approach it differently?
Upvotes: 0
Views: 115
Reputation: 167581
I would simplify the key to match on Row
and then write templates to transform the Cells:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="a-group" match="Row" use="Cell[@name = 'A']"/>
<xsl:template match="Sheet">
<Beholdninger>
<xsl:variable name="group-heads" select="Row[generate-id() = generate-id(key('a-group', Cell[@name = 'A'])[1])]"/>
<Unique>
<xsl:value-of select="count($group-heads)"/>
</Unique>
<AllePoster>
<xsl:apply-templates select="$group-heads"/>
</AllePoster>
</Beholdninger>
</xsl:template>
<xsl:template match="Row">
<xsl:apply-templates select="Cell[@name = 'A'] | key('a-group', Cell[@name = 'A'])/Cell[@name = 'B']"/>
</xsl:template>
<xsl:template match="Cell[@name = 'A']">
<A>
<xsl:value-of select="."/>
</A>
</xsl:template>
<xsl:template match="Cell[@name = 'B']">
<p>
<B>
<xsl:value-of select="."/>
</B>
</p>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/ejivJsd/1
Upvotes: 1