【问题标题】:xslt add number from regular expression to node valuexslt将正则表达式中的数字添加到节点值
【发布时间】:2018-03-02 20:16:12
【问题描述】:

我有以下xml sn-p:

<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 月份,其中x 是MEMO 节点中PARC 之后的前两位数字表示的数字,将由常规提取表达式(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>

我不知道如何继续,如果您能帮助我,我将不胜感激。

【问题讨论】:

  • 至于正则表达式,为什么PARC \(\d\d\) 带有转义的( 和) 尽管输入在PARC 03/05 中不包含任何此类字符?如果你想使用正则表达式和日期算术,你可以使用 XSLT 2 或更高版本吗?
  • 我可以使用 XSLT2 或更高版本,并且我将正则表达式更正为“sed”正则表达式。

标签: xml xslt xml-parsing


【解决方案1】:

我准备了一个示例脚本,一步一步地展示如何得到你想要的结果 想要。

因为这个脚本使用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 - 原始日期。
  • 2018-01-20 - 移动日期(带有 - 字符)。
  • 20180120 - 将日期转换为字符串,不带 - 字符。

实际上,您只需要上述打印输出中的最后一个。

【讨论】:

  • 谢谢,经过第一次测试,这似乎对我有用!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-26
  • 2012-07-05
  • 1970-01-01
  • 2011-04-13
相关资源
最近更新 更多