Q:

xslt add number from regular expression to node value

I have the following xml snippet:
<STMTTRN><TRNTYPE>PAYMENT</TRNTYPE>
<DTPOSTED>20171120</DTPOSTED>
<TRNAMT>-645.29</TRNAMT>
<FITID>2017112049840000000061890000000035</FITID>
<MEMO>ARGO SEGUROS  PARC 03/05 SAO PAULO   BR</MEMO>
</STMTTRN>

And I'd like to add to the DTPOSTED node x-1 months where x is the number indicated by the first two digits after PARC in the MEMO node as would be extracted by the regular expression (sed style)
PARC \([0-9][0-9]\)/[0-9][0-9]

So in the example above I'd like to obtain as output:
<STMTTRN><TRNTYPE>PAYMENT</TRNTYPE>
<DTPOSTED>20180120</DTPOSTED>
<TRNAMT>-645.29</TRNAMT>
<FITID>2017112049840000000061890000000035</FITID>
<MEMO>ARGO SEGUROS  PARC 03/05 SAO PAULO   BR</MEMO>
</STMTTRN>

I have no clue how to proceed and I'd appreciate it if you could help me. 

A:

I prepared an example script, showing step by step how to get the result you
want.
Because this script uses xs namespace, the transform tag must contain
xmlns:xs="http://www.w3.org/2001/XMLSchema".
It must contain also exclude-result-prefixes="#all", otherwise the output
would have contained xmlns:xs="http://www.w3.org/2001/XMLSchema".
The basic logic is contained in template matching DTPOSTED.
In my script it prints:

Original content of DTPOSTED.
All intermediate values (separated with /).
The final value (shifted date string).

In your script omit any xsl:value-of except the last one and any
xsl:text used as separators.
And now let's get down to the details:

replace function replaces the whole text with the content of
the first capturing group, in your case 03.
To drop the leading 0, I used number function, so now we have
number of months to add (so far, not decreased).
The duration string is composed of 3 parts:

P - period indicator,
the above number of months - 1,
'M' - unit indicator (months).

In order to perform date arithmetic, we need the original date,
converted to xs:date type. I stored it in d1 variable.
The shifted date is computed according to formula
$d1 + xs:yearMonthDuration($dur). I stored it in d2 variable.
And the last stage is to print $d2, but without - chars.

So the whole script looks like below:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all">
  <xsl:output method="xml" encoding="UTF-8" indent="yes" />

  <xsl:template match="DTPOSTED">
    <DTPOSTED>
      <xsl:value-of select="."/> <!-- Original value (string) -->
      <xsl:text> / </xsl:text>
      <!-- Duration (string) -->
      <xsl:variable name="dur" select="concat('P', 
        number(replace(../MEMO,'\D+(\d\d)/.+','$1')) - 1, 'M')"/>
      <xsl:value-of select="$dur"/>
      <xsl:text> / </xsl:text>
      <!-- Original value (date) -->
      <xsl:variable name="d1" select="xs:date(concat(substring(., 1, 4), '-',
        substring(., 5, 2), '-', substring(., 7, 2)))"/>
      <xsl:value-of select="$d1"/>
      <xsl:text> / </xsl:text>
      <!-- "Shifted" date -->
      <xsl:variable name="d2" select="$d1 + xs:yearMonthDuration($dur)"/>
      <xsl:value-of select="$d2"/>
      <xsl:text> / </xsl:text>
      <!-- "Shifted" date without '-' chars -->
      <xsl:value-of select="format-date($d2, '[Y0001][M01][D01]')"/>
    </DTPOSTED>
  </xsl:template>

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

For your sample source it prints DTPOSTED as:
<DTPOSTED>20171120 / P2M / 2017-11-20 / 2018-01-20 / 20180120</DTPOSTED>

As I noted before, it contains:

20171120 - original string.
P2M - Period string.
2017-11-20 - original date.
2018-01-20 - shifted date (with - chars).
20180120 - shifted date as a string, without - chars.

Actually you need only the last from the above prinouts.

