alex
alex

Reputation: 89

XSLT position of chosen elements

I'd like to display position of chosen nodes.

xslt:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:call-template name="Convert"></xsl:call-template>

    <xsl:template name="Convert">
        <Pos>
            <Type><xsl:value-of select="type"/></Type>
            <LineNumber><xsl:value-of select="position()"/></LineNumber>
            ...
        </Pos>
    </xsl:template>
</xsl:stylesheet>

My xml is:

<OrderPositions>
    <Pos>
         <Type>simple</Type>
         <LineNumber>1</LineNumber>
         ...
    </Pos>
    <Pos>
         <Type>complex</Type>
         <LineNumber>2</LineNumber>
         ...
    </Pos>
    <Pos>
         <Type>simple</Type>
         <LineNumber>3</LineNumber>
         ...
    </Pos>
    <Pos>
         <Type>complex</Type>
         <LineNumber>4</LineNumber> 
         ...
    </Pos>
</OrderPositions>

Trying to exclude "complex" types in xslt using <xsl:choose> + <xsl:when test="type='simple'"> gives LineNumber 1,3,5,7 etc. What is the proper way to choose only "simple" (remove "complex") types and display it positions like 1,2,3,4 etc.?

Upvotes: 2

Views: 323

Answers (2)

Daniel Haley
Daniel Haley

Reputation: 52858

You could also use xsl:number...

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

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Pos[Type='complex']"/>

    <xsl:template match="LineNumber">
        <xsl:copy>
            <xsl:number count="Pos[Type='simple']"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Upvotes: 1

kjhughes
kjhughes

Reputation: 111621

You can copy all nodes over to the output by default using the identity transformation, modified to suppress complex Pos elements and output LineNumber elements with values set to the count of all preceding simple Pos elements:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Pos[Type = 'complex']"/>

  <xsl:template match="LineNumber">
    <xsl:copy>
      <xsl:value-of select="count(preceding::Pos[Type = 'simple']) + 1"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Then your output will be:

<?xml version="1.0" encoding="UTF-8"?>
<OrderPositions>
  <Pos>
      <Type>simple</Type>
      <LineNumber>1</LineNumber>
    ...
  </Pos>

  <Pos>
      <Type>simple</Type>
      <LineNumber>2</LineNumber>
    ...
  </Pos>

</OrderPositions>

Upvotes: 3

Related Questions