0

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!

Pick
  • 55
  • 4
  • 1
    Please explain the **exact** logic you are trying to implement. It seems you have a recursive structure of `ArchiveUnit` containing other `ArchiveUnit`, but you only want to number the 2nd level?? – michael.hor257k Aug 25 '23 at 11:58
  • My source xml file contains a hierarchy of ArchiveUnits. And I would like to increment only level 2 ArchiveUnits. Hence the condition: . For each level 2 ArchiveUnit, I want an increment of +1. – Pick Aug 25 '23 at 12:05

1 Answers1

0

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>
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • your suggestion works, thank you. But in my example, the first ArchiveUnit (root) is in a . The other ArchiveUnits are in a . That's why, in my basic XSLT, I treat the two separately. My requirement: transform the content of the first ArchiveUnit into an . The child ArchiveUnits are in a . And ArchiveUnit level 2 has an increment. – Pick Aug 25 '23 at 12:50
  • I am not sure I understand this correctly. The first `ArchiveUnit` is NOT "root". The root element in the input is `ArchiveTransfer` - and at least in theory, it could have multiple `ArchiveUnit` descendants of the first level. So it's not clear what does `archdesc` represents. You could either have it in the template matching the root element, or you could determine the name of the element that represents `ArchiveUnit` dynamically, based on the value of $level. Are you limited to XSLT 1.0? – michael.hor257k Aug 25 '23 at 12:59
  • you're right, the root element of the XML is ArchiveTransfer. I'm not being precise, sorry. In my case, there can only be one encompassing ArchiveUnit. So, only one transformed archdesc. But this "root" can contain as many ArchiveUnits as necessary. I'm unfortunately limited to XSLT 1.0 yes. Thanks – Pick Aug 25 '23 at 13:21
  • So do I understand correctly that `ArchiveUnit` should become either `archdesc` (when level=1) or `c` (in all other cases)? And that the `dsc` wrapper should also appear only at level 1? – michael.hor257k Aug 25 '23 at 13:34
  • Not exactly yet. The first ArchiveUnit is an . The following are recursive in a single . is a child of and contains from ArchiveUnit level 2 and below. My XML example (first post) shows the structure if it's clearer. – Pick Aug 25 '23 at 13:40
  • I am afraid I don't see the difference between what I said and what you said. I added an "improved" version to my answer. AFAICT, this returns the exact result shown in your question. – michael.hor257k Aug 25 '23 at 13:53
  • That's exactly it, thank you very much. I'm not familiar with the functions you used (mode="top" attribute and the select="false() in the param). I've just consulted the documentation. It seems clear to me but I wouldn't have found it on my own. Thanks for your time! – Pick Aug 25 '23 at 14:48