日期时间转换导致 FORG0001 无效的日期时间值 - XSLT 3.0

Date time conversion results in FORG0001 Invalid dateTime value - XSLT 3.0

资源:

Java 1.8
Saxon-HE-10.3
XSLT3.0

我正在合并 2 个 XML 文件并希望在合并的输出文件中进行日期操作 xml。

  1. 我正在使用 java 将 2 个文件作为输入并生成合并的 xml - 这很好用。
  2. 现在,我在合并操作后的 xsl 中添加了日期操作。
  3. 日期操作 - 将给定日期转换为 epoch/milliseconds

输入文件自带的日期格式

<PROP NAME="START_DATE">
<PVAL>16-Aug-2018</PVAL>
</PROP>

问题是当我尝试将给定日期转换为 dateTime 或转换为纪元时,编译时出现以下错误。

Error at char 10 in expression in xsl:value-of/@select on line 60 column 105 of CASTransform.xsl:   FORG0001  Invalid dateTime value "/01--20T00:00:00" (Non-numeric year component) at template reformat-date on line 55 of CASTransform.xsl:
 invoked by xsl:call-template at file:/home/Merger/scripts/CASTransform.xsl#50 In template rule with match="element(Q{}RECORDS)/element(Q{}RECORD)/element(Q{}PROP)[(Q{http://www.w3.org/2001/XMLSchema}string(data(attribute::attribute(Q{}NAME)))) eq "START_DATE"]/element(Q{}PVAL)" on line 48 of CASTransform.xsl
 invoked by xsl:apply-templates at file:/home/Merger/scripts/CASTransform.xsl#45 In template rule with match="(element()|(text()|(comment()|processing-instruction())))" on line 43 of CASTransform.xsl
 invoked by xsl:apply-templates at file:/home/Merger/scripts/CASTransform.xsl#35 at template main on line 14 of CASTransform.xsl: Exception in thread "main" net.sf.saxon.s9api.SaxonApiException: Invalid dateTime value "/01--20T00:00:00" (Non-numeric year component)
    at net.sf.saxon.s9api.Xslt30Transformer.callTemplate(Xslt30Transformer.java:488)

XSL 代码

    <xsl:stylesheet version="3.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:map="http://www.w3.org/2005/xpath-functions/map"
        xmlns:array="http://www.w3.org/2005/xpath-functions/array"
        exclude-result-prefixes="#all">
        <xsl:mode on-no-match="shallow-copy"/>
        <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
        <xsl:param name="mapData"/>
        <xsl:template match="/" name="main">
            <RECORDS>
                <xsl:variable name="file1" select="map:get($mapData, '1')" />
                <xsl:variable name="input-doc1" as="document-node()" select="doc($file1)"/>
                <xsl:variable name="file2" select="map:get($mapData, '2')" />
                <xsl:variable name="input-doc2" as="document-node()" select="doc($file2)"/>
                <xsl:merge>
                    <xsl:merge-source name="doc1" select="$input-doc1/RECORDS/RECORD">
                        <xsl:merge-key select="PROP[@NAME = 'Id']/PVAL"></xsl:merge-key>
                    </xsl:merge-source>
                    <xsl:merge-source name="doc2" select="$input-doc2/RECORDS/RECORD">
                        <xsl:merge-key select="PROP[@NAME = 'Id']/PVAL"></xsl:merge-key>
                    </xsl:merge-source>
                    <xsl:merge-action>
                        <xsl:if test="current-merge-group('doc1')">
                            <xsl:copy>
                                <xsl:apply-templates select="*, current-merge-group('doc2')/(* except PROP[@NAME = 'Id'])"/>
                            </xsl:copy>
                        </xsl:if>
                    </xsl:merge-action>
                </xsl:merge>
            </RECORDS>
        </xsl:template>
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()" />
            </xsl:copy>
        </xsl:template>
        <xsl:template match="RECORDS/RECORD/PROP[@NAME = 'START_DATE']/PVAL | RECORDS/RECORD/PROP[@NAME = 'END_DATE']/PVAL">
        <xsl:element name="{name()}">
            <xsl:call-template name="reformat-date">
                <xsl:with-param name="date" select="." />
            </xsl:call-template>
        </xsl:element>
    </xsl:template>
    <xsl:template name="reformat-date">
        <xsl:param name="date" />
        <xsl:variable name="dd" select="substring($date,1,2)" />
        <xsl:variable name="mmm" select="upper-case(substring($date,4,3))" />
        <xsl:variable name="yyyy" select="substring($date,8,4)" />
        <xsl:variable name="mmm">
            <xsl:choose>
                <xsl:when test="$mmm = 'JAN'">01</xsl:when>
                <xsl:when test="$mmm = 'FEB'">02</xsl:when>
                <xsl:when test="$mmm = 'MAR'">03</xsl:when>
                <xsl:when test="$mmm = 'APR'">04</xsl:when>
                <xsl:when test="$mmm = 'MAY'">05</xsl:when>
                <xsl:when test="$mmm = 'JUN'">06</xsl:when>
                <xsl:when test="$mmm = 'JUL'">07</xsl:when>
                <xsl:when test="$mmm = 'AUG'">08</xsl:when>
                <xsl:when test="$mmm = 'SEP'">09</xsl:when>
                <xsl:when test="$mmm = 'OCT'">10</xsl:when>
                <xsl:when test="$mmm = 'NOV'">11</xsl:when>
                <xsl:when test="$mmm = 'DEC'">12</xsl:when>
            </xsl:choose>
        </xsl:variable>
        <xsl:variable name="temp1" as="xs:string" select="string-join(($yyyy,$mmm,$dd),'-')" />
        <xsl:value-of select="$temp1" />
    </xsl:template>
</xsl:stylesheet>

上面的 XSL 代码工作得很好,$temp1 给出了正确的日期,比如 2018-08-16。

现在,当我尝试将其转换为 dateTime 变量时,出现上述编译错误。

出现错误的代码:

<xsl:variable name="temp2" as="xs:dateTime" select="xs:dateTime(concat($temp1,'T00:00:00'))"/>

也试过了:

<xsl:value-of select="floor((xs:dateTime(concat($temp1,'T00:00:00')) - xs:dateTime('1970-01-01T00:00:00')) div xs:dayTimeDuration('PT1S')) "/>

请求您的帮助,因为这是我的第一个 XSL 项目。

完整堆栈跟踪:

 Error at char 10 in expression in xsl:value-of/@select on line 60 column 105 of CASTransform.xsl:
      FORG0001  Invalid dateTime value "/01--20T00:00:00" (Non-numeric year component)
    at template reformat-date on line 55 of CASTransform.xsl:
         invoked by xsl:call-template at file:/home/Merger/scripts/CASTransform.xsl#50
      In template rule with match="element(Q{}RECORDS)/element(Q{}RECORD)/element(Q{}PROP)[(Q{http://www.w3.org/2001/XMLSchema}string(data(attribute::attribute(Q{}NAME)))) eq "START_DATE"]/element(Q{}PVAL)" on line 48 of CASTransform.xsl
         invoked by xsl:apply-templates at file:/home/Merger/scripts/CASTransform.xsl#45
      In template rule with match="(element()|(text()|(comment()|processing-instruction())))" on line 43 of CASTransform.xsl
         invoked by xsl:apply-templates at file:/home/Merger/scripts/CASTransform.xsl#35
    at template main on line 14 of CASTransform.xsl:
    Exception in thread "main" net.sf.saxon.s9api.SaxonApiException: Invalid dateTime value "/01--20T00:00:00" (Non-numeric year component)
            at net.sf.saxon.s9api.Xslt30Transformer.callTemplate(Xslt30Transformer.java:488)
            at com.tracer.Merger.CASExportInput.trans(CASExportInput.java:38)
            at com.tracer.Merger.CASExportInput.main(CASExportInput.java:58)
    Caused by: ValidationException: Invalid dateTime value "/01--20T00:00:00" (Non-numeric year component)
            at net.sf.saxon.type.ValidationFailure.makeException(ValidationFailure.java:406)
            at net.sf.saxon.expr.CastExpression.doCast(CastExpression.java:385)
            at net.sf.saxon.expr.CastExpression.evaluateItem(CastExpression.java:402)
            at net.sf.saxon.expr.CastExpression.evaluateItem(CastExpression.java:30)
            at net.sf.saxon.expr.Expression.iterate(Expression.java:872)
            at net.sf.saxon.expr.AtomicSequenceConverter.iterate(AtomicSequenceConverter.java:304)
            at net.sf.saxon.expr.Expression.process(Expression.java:949)
            at net.sf.saxon.expr.instruct.ValueOf.processLeavingTail(ValueOf.java:340)
            at net.sf.saxon.expr.LetExpression.processLeavingTail(LetExpression.java:746)
            at net.sf.saxon.expr.instruct.Block.processLeavingTail(Block.java:752)
            at net.sf.saxon.expr.instruct.NamedTemplate.expand(NamedTemplate.java:264)
            at net.sf.saxon.expr.instruct.CallTemplate$CallTemplatePackage.processLeavingTail(CallTemplate.java:549)
            at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:478)
            at net.sf.saxon.expr.instruct.ApplyTemplates.apply(ApplyTemplates.java:351)
            at net.sf.saxon.expr.instruct.ApplyTemplates.process(ApplyTemplates.java:285)
            at net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:352)
            at net.sf.saxon.expr.instruct.Copy.processLeavingTail(Copy.java:429)
            at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:384)
            at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:568)
            at net.sf.saxon.expr.instruct.ApplyTemplates.apply(ApplyTemplates.java:351)
            at net.sf.saxon.expr.instruct.ApplyTemplates.process(ApplyTemplates.java:285)
            at net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:352)
            at net.sf.saxon.expr.instruct.Copy.processLeavingTail(Copy.java:429)
            at net.sf.saxon.expr.instruct.Instruction.process(Instruction.java:142)
            at net.sf.saxon.expr.parser.ExpressionTool.getIteratorFromProcessMethod(ExpressionTool.java:643)
            at net.sf.saxon.expr.instruct.Instruction.iterate(Instruction.java:374)
            at net.sf.saxon.expr.instruct.Choose.iterate(Choose.java:1019)
            at net.sf.saxon.expr.sort.MergeInstr.lambda$iterate[=16=](MergeInstr.java:543)
            at net.sf.saxon.expr.ContextMappingIterator.next(ContextMappingIterator.java:61)
            at net.sf.saxon.om.SequenceIterator.forEachOrFail(SequenceIterator.java:135)
            at net.sf.saxon.expr.sort.MergeInstr.processLeavingTail(MergeInstr.java:823)
            at net.sf.saxon.expr.instruct.Instruction.process(Instruction.java:142)
            at net.sf.saxon.expr.LetExpression.process(LetExpression.java:625)
            at net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:352)
            at net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:298)
            at net.sf.saxon.expr.instruct.NamedTemplate.expand(NamedTemplate.java:264)
            at net.sf.saxon.trans.XsltController.callTemplate(XsltController.java:850)
            at net.sf.saxon.s9api.Xslt30Transformer.callTemplate(Xslt30Transformer.java:480)
            ... 2 more

Java 用于输入文件的代码:

package com.tracer.Merger.CASMerger;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import javax.xml.transform.stream.StreamSource;
import net.sf.saxon.s9api. * ;

public class CASExportInput {
  public static void trans(String XSLFile, String File1, String File2, String OutputFileName, String OutputFilePath) throws SaxonApiException {
    String MergedFile = OutputFilePath.concat(OutputFileName);

    Processor processor = new Processor(false);
    XsltCompiler compiler = processor.newXsltCompiler();
    XsltExecutable exp = compiler.compile(new StreamSource(new File(XSLFile)));
    Serializer out = processor.newSerializer(new File(MergedFile));
    out.setOutputProperty(Serializer.Property.METHOD, "xml");
    out.setOutputProperty(Serializer.Property.INDENT, "yes");
    Xslt30Transformer trans = exp.load30();

    Map < String,
    String > mapData = new HashMap < String,
    String > ();
    mapData.put("1", File1);
    mapData.put("2", File2);
    HashMap < QName,
    XdmValue > parameters = new HashMap < >();
    parameters.put(new QName("mapData"), XdmMap.makeMap(mapData));
    trans.setStylesheetParameters(parameters);

    trans.callTemplate(new QName("main"), out);
    System.out.println("Output written to : " + MergedFile);

  }

  public static void main(String args[]) throws SaxonApiException {

    if (args.length < 3) System.out.println("\nPlease check if you have entered arguments properly...");
    String XSLFile = args[0].toString().trim();
    String File1 = args[1].toString().trim();
    String File2 = args[2].toString().trim();
    String FileName1 = File1.substring(File1.lastIndexOf("/") + 1, File1.length() - 4);
    String FileName2 = File2.substring(File2.lastIndexOf("/") + 1, File2.length() - 4);
    String OutputFilePath = File1.substring(0, File1.lastIndexOf("/") + 1);
    String OutputFileName = FileName1.concat("-" + FileName2 + ".xml");
    trans(XSLFile, File1, File2, OutputFileName, OutputFilePath);
  }
}

不确定是什么问题。但是,我卸载并重新安装了 Java 1.8,问题得到了解决。 xsl 或 java 代码中未进行任何更改。