【问题标题】:XSLT transform failed sometimesXSLT 转换有时会失败
【发布时间】:2018-10-15 09:13:11
【问题描述】:

我不是 XSLT 方面的专家,我有一个无法用转换器解释的问题。此问题仅在生产使用中出现:我自己无法重现它。

我有一个接收 XML 消息的进程(通过 JMS 队列)。此消息必须转换为另一个 XML。

这是执行转换的代码:

final TransformerFactory factory = TransformerFactory.newInstance();
final Templates templates = factory.newTemplates(new StreamSource(xsl));

final Transformer xformer = templates.newTransformer();

try (final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
     final InputStream inputStream = new ByteArrayInputStream(message.getBytes())) {

    final Source source = new StreamSource(inputStream);
    final Result result = new StreamResult(outputStream);

    xformer.transform(source, result);

    ....
}

在原始 XML 中,我收到格式为 yyyyMMdd(作为字符串)的日期,但我需要格式为 yyyy-MM-dd 的日期。

<xsl:template match="INVOICE_DATE_FROM">
    <xsl:call-template name="fctFormatDate">
        <xsl:with-param name="elementName" select="'dateFrom'"/>
        <xsl:with-param name="dateParam">
            <xsl:value-of select="string(.)"/>
        </xsl:with-param>
    </xsl:call-template>
</xsl:template>

<xsl:template name="fctFormatDate">
    <xsl:param name="elementName"/>
    <xsl:param name="dateParam"/>
    <xsl:if test="$dateParam != '' and $dateParam != '00000000'">
        <xsl:element name="{$elementName}">
           <xsl:value-of select="concat(concat(concat(concat(substring($dateParam, '1', '4'), '-'), substring($dateParam, number('5'), '2')), '-'), substring($dateParam, number('7'), '2'))"/>
        </xsl:element>
    </xsl:if>
</xsl:template>

大多数情况下,它都有效,并且我获得了格式正确的日期。但有时,我会收到类似的东西:

<dateFrom>IN18-07-01</dateFrom>

有人已经见过这个问题之王了吗?或者可以告诉我这段代码有什么问题吗?

非常感谢。

编辑

只有一个精度:我们使用 XSLT 1.0

编辑 2

这是 XML 的一部分(我无法向您展示更多内容,因为私有数据将品牌产品作为标签名称)。

<DUNNING_LINE SEGMENT="1">
    <INVOICE_NUMBER>*************</INVOICE_NUMBER>
    <INVOICE_DUE_DATE>20180731</INVOICE_DUE_DATE>
    <INVOICE_TOTAL_AMOUNT>39.49</INVOICE_TOTAL_AMOUNT>
    <INVOICE_PAID_AMOUNT>0.00</INVOICE_PAID_AMOUNT>
    <INVOICE_DUE_AMOUNT>39.49</INVOICE_DUE_AMOUNT>
    <INVOICE_DATE_FROM>20180701</INVOICE_DATE_FROM>
    <INVOICE_DATE_TO>20180731</INVOICE_DATE_TO>
    <INVOICE_POSTING_DATE>20180630</INVOICE_POSTING_DATE>
</DUNNING_LINE>

【问题讨论】:

  • 可能服务器中的语言设置与您的测试环境中的不同。这可能会更改默认日期和时间默认设置。
  • 所有服务器都是英文的。但我不明白为什么在这种情况下它可以改变任何东西。原始值是文本 (20180701),XSLT 要求将其更改为格式化文本 (2018-07-01)。此外,99% 的消息都得到了很好的转化。
  • 我认为“IN”来自原始标签名称。我在其他情况下收到了类似 INVO-07-01 的信息
  • 向我们展示一个最小但完整的输入 XML,在该问题发生的地方,我们可能能够分辨出什么是错误的,仅显示没有输入的代码不允许任何人告诉什么是错的,其他而不是假设输入不是你说的格式。
  • 看起来 XSLT 不是问题,而是生成 XML 的原因。考虑向xsl:element 代码块添加注释以允许您查看原始值。例如&lt;xsl:comment&gt;&lt;xsl:value-of select="$dateParam" /&gt;&lt;/xsl:comment&gt;.

标签: java xml xslt xslt-1.0


【解决方案1】:

从简化代码开始:

<xsl:value-of select="concat(concat(concat(concat(substring($dateParam, '1', '4'), '-'), substring($dateParam, number('5'), '2')), '-'), substring($dateParam, number('7'), '2'))"/>

concat() 接受任意数量的参数,并且子字符串的第二个和第三个参数是数字,所以这减少到

concat(substring($dateParam, 1, 4), '-', 
       substring($dateParam, 5, 2), '-', 
       substring($dateParam, 7, 2))

这不会解决您的问题,但调试代码的第一步应该始终是摆脱不必要的复杂性。

我怀疑的问题是 $dateParam 已经保存了不正确的数据,但当然你没有向我们展示足够的信息让我能够测试这个理论。

【讨论】:

  • 谢谢。当我开始做这个项目时(一周前),我已经完成了这个简化。但是由于它还没有部署到生产环境中,所以我向您展示了生产环境中的代码。输入 XML 怎么样,我只是添加了我可以添加的内容。但是当我在测试中发送完全相同的输入时,没有错误。在生产中,我有不到 0.1% 的失败过程(所有输入都具有相同的结构)。
  • 无论多么令人沮丧,您一定很清楚,您没有为读者提供足够的信息以使他们能够找到此错误。
猜你喜欢
  • 2020-06-13
  • 1970-01-01
  • 1970-01-01
  • 2018-01-17
  • 1970-01-01
  • 1970-01-01
  • 2014-05-01
  • 2013-02-18
  • 1970-01-01
相关资源
最近更新 更多