Search code examples
loopsxsltincrement

Add an increment from XSLT-transformed nodes


I would like to add an increment to an XML element by counting the number of nodes in the source file. This increment is placed in a particular condition that counts the position in a tree structure.

Here's an example of the source file:

<ArchiveTransfer>
  <DataObjectPackage>
    <DescriptiveMetadata>
      <ArchiveUnit id="ID20230407121050277">
        <Content>
          <Title>Information</Title>
        </Content>
        <ArchiveUnit id="ID20230407121050344">
          <Content>
            <Title>2212 Blogs</Title>
          </Content>
          <ArchiveUnit id="ID20230407121054394">
            <Content>
              <Title>Export eSPRIT</Title>
            </Content>
            <ArchiveUnit id="ID20230407121054576">
              <Content>
                <Title>eSPRIT</Title>
              </Content>
            </ArchiveUnit>
          </ArchiveUnit>
        </ArchiveUnit>
        <ArchiveUnit id="ID20230407121054610">
          <Content>
            <Title>2212 Newsletter</Title>
          </Content>
          <ArchiveUnit id="ID20230407121054710">
            <Content>
              <Title>Entreprises</Title>
            </Content>
          </ArchiveUnit>
        </ArchiveUnit>
      </ArchiveUnit>
    </DescriptiveMetadata>
  </DataObjectPackage>
</ArchiveTransfer>

Je voudrais obtenir le résultat suivant :

<ead>
   <archdesc>
      <did>
         <unittitle>Information</unittitle>
      </did>
      <dsc>
         <c>
            <did>
               <unitid>1</unitid>
               <unittitle>2212 Blogs</unittitle>
            </did>
            <c>
               <did>
                  <unittitle>Export eSPRIT</unittitle>
               </did>
               <c>
                  <did>
                     <unittitle>eSPRIT</unittitle>
                  </did>
               </c>
            </c>
         </c>
         <c>
            <did>
               <unitid>2</unitid>
               <unittitle>2212Newsletter </unittitle>
            </did>
            <test>1</test>
            <c>
               <did>
                  <unittitle>Entreprises</unittitle>
               </did>
            </c>
         </c>
      </dsc>
   </archdesc>
</ead>

Voici ma feuille XSLT :

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="xml" encoding="utf-8"/>
    <xsl:variable name="unitidCounter" select="1"/>

    <xsl:template match="/">
        <xsl:apply-templates
            select="//ArchiveTransfer/DataObjectPackage/DescriptiveMetadata/ArchiveUnit"/>
    </xsl:template>

    <xsl:template match="//Archive/DescriptiveMetadata/ArchiveUnit">
        <ead>
            <archdesc>
                <xsl:call-template name="did"/>
                <dsc>
                    <xsl:apply-templates select="ArchiveUnit"/>
                </dsc>
            </archdesc>
        </ead>
    </xsl:template>

    <xsl:template match="ArchiveUnit">
        <c>
            <xsl:call-template name="did"/>
            <xsl:apply-templates select="ArchiveUnit">
                <xsl:with-param name="unitidCounter" select="$unitidCounter + 1"/>
            </xsl:apply-templates>
        </c>
    </xsl:template>
    <xsl:template name="did">
        <did>
            <xsl:if test="count(ancestor::ArchiveUnit) = 1">
                <unitid>
                    <xsl:value-of select="$unitidCounter"/>
                </unitid>
            </xsl:if>
        </did>
    </xsl:template>

    <xsl:template match="Content/Title">
        <unittitle type="titre" label="Intitulé de l'unité documentaire">
            <xsl:apply-templates select="@language"/>
            <xsl:apply-templates/>
        </unittitle>
    </xsl:template>

</xsl:stylesheet>

I try to increment the unitidCounter variable but the result I get is always 1. I think I'm incrementing this variable wrongly, but I can't find my error. Any ideas? Thanks a lot!


Solution

  • I would suggest you try something along the lines of:

    XSLT 1.0

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <xsl:template match="/ArchiveTransfer">
        <ead>
            <xsl:apply-templates select="DataObjectPackage/DescriptiveMetadata/ArchiveUnit"/>
        </ead>
    </xsl:template>
    
    <xsl:template match="ArchiveUnit">
        <xsl:param name="level" select="1"/>
        <c>
            <did>
                <xsl:if test="$level=2">
                    <unitid>
                        <xsl:value-of select="position()"/>
                    </unitid>
                </xsl:if>
                <unittitle>
                    <xsl:value-of select="Content/Title"/>
                </unittitle>
            </did>
            <dsc>
                <xsl:apply-templates select="ArchiveUnit">
                    <xsl:with-param name="level" select="$level + 1"/>
                </xsl:apply-templates>
            </dsc>
        </c>
    </xsl:template>
    
    </xsl:stylesheet>
    

    Added:

    With so many exceptions for the 1st and 2nd level of the hierarchy, I would probably do something like:

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <xsl:template match="/ArchiveTransfer">
        <ead>
            <xsl:apply-templates select="DataObjectPackage/DescriptiveMetadata/ArchiveUnit" mode="top"/>
        </ead>
    </xsl:template>
    
    <xsl:template match="ArchiveUnit" mode="top">
        <archdesc>
            <did>
                <unittitle>
                    <xsl:value-of select="Content/Title"/>
                </unittitle>
            </did>
            <dsc>
                <xsl:apply-templates select="ArchiveUnit">
                    <xsl:with-param name="isLevel2" select="true()"/>
                </xsl:apply-templates>
            </dsc>
        </archdesc>
    </xsl:template>
    
    <xsl:template match="ArchiveUnit">
        <xsl:param name="isLevel2" select="false()"/>
        <c>
            <did>
                <xsl:if test="$isLevel2">
                    <unitid>
                        <xsl:value-of select="position()"/>
                    </unitid>
                </xsl:if>
                <unittitle>
                    <xsl:value-of select="Content/Title"/>
                </unittitle>
            </did>
            <xsl:apply-templates select="ArchiveUnit"/>
        </c>
    </xsl:template>
    
    </xsl:stylesheet>