xslt将正则表达式中的数字添加到节点值

问题描述 投票:-1回答:1

我有以下xml片段:

<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>

并且我想添加到DTPOSTED节点x-1月,其中xPARC节点中MEMO之后的前两位数表示的数字,将由正则表达式提取(sed样式)

PARC \([0-9][0-9]\)/[0-9][0-9]

所以在上面的例子中我想获得输出:

<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>

我不知道如何继续,如果你能帮助我,我会很感激。

xml xslt xml-parsing
1个回答
2
投票

我准备了一个示例脚本,逐步显示如何获得所需的结果。

因为此脚本使用xs名称空间,所以transform标记必须包含xmlns:xs="http://www.w3.org/2001/XMLSchema"

它必须包含exclude-result-prefixes="#all",否则输出将包含xmlns:xs="http://www.w3.org/2001/XMLSchema"

基本逻辑包含在模板匹配DTPOSTED中。在我的脚本中打印:

  • DTPOSTED的原始内容。
  • 所有中间值(用/分隔)。
  • 最终值(移位日期字符串)。

在你的脚本中省略除最后一个之外的任何xsl:value-of以及用作分隔符的任何xsl:text

现在让我们来看看细节:

  • replace函数用第一个捕获组的内容替换整个文本,在您的情况下03
  • 为了放弃领先的0,我使用了number函数,所以现在我们有几个月要添加(到目前为止,没有减少)。
  • 持续时间字符串由3部分组成: P - 期间指标, 上述月份数 - 1, 'M' - 单位指标(月)。
  • 为了执行日期算术,我们需要原始日期,转换为xs:date类型。我把它存储在d1变量中。
  • 移位日期根据公式$d1 + xs:yearMonthDuration($dur)计算。我把它存储在d2变量中。
  • 最后一个阶段是打印$d2,但没有-字符。

所以整个脚本如下所示:

<?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>

对于您的示例源,它将DTPOSTED打印为:

<DTPOSTED>20171120 / P2M / 2017-11-20 / 2018-01-20 / 20180120</DTPOSTED>

正如我之前提到的,它包含:

  • 20171120 - 原始字符串。
  • P2M - 期间字符串。
  • 2017-11-20 - 原始日期。
  • qazxsw poi - 轮班日期(与qazxsw poi排行榜)。
  • 2018-01-20 - 将日期换成字符串,没有-字符。

实际上你只需要上面打印输出中的最后一个。

© www.soinside.com 2019 - 2024. All rights reserved.