【问题标题】:XPTY0004: Required item type of first operand of '>' is numeric; supplied value has item type xs:stringXPTY0004:“>”的第一个操作数的必需项类型是数字;提供的值具有项目类型 xs:string
【发布时间】:2018-03-28 12:52:05
【问题描述】:

toComplie 字符串包含所有函数的定义,如 sum、multiply 等,由 if ($a > 0) then (iaf:numeric-equal(iaf:numeric-multiply($b, $c), $d)) else (true()) 附加

执行这个的sn-p是:

XQueryExecutable queryExecutable = xqueryCompiler.compile(toCompile.toString());
XQueryEvaluator xqueryEvaluator = queryExecutable.load();

//setExternalVariables(): function used to set the variables for the test contains below line
        xqueryEvaluator.setExternalVariable(new QName(memberName), value);
setExternalVariables(xqueryEvaluator,assertionExpression);

xqueryResult = xqueryEvaluator.evaluate();

抛出异常如下:

XPTY0004:'>'的第一个操作数的必需项类型是数字;提供的值具有项目类型 xs:string


如果需要更多信息来理解这个问题,请告诉我。这是因为其他部分,还是其他原因?

编辑: 在 setExternalVariables() 中,我使用 for-each 循环使用下面的行添加变量。 value 变量的类型为 net.sf.saxon.s9api.XdmValue

xqueryEvaluator.setExternalVariable(new QName(memberName), value);

setExternalVariables()方法中,

// FACT_VALUE_FORMAT:%s;%s --  where first string is value and second gives information about precision.
//current option
XdmAtomicValue atomicValue = new XdmAtomicValue(String.format(FACT_VALUE_FORMAT, fact.getValue(),getPrecision(fact.getDecimals())));
// alternative 1
atomicValue = new XdmAtomicValue(getDoubleValue(fact));
//alternative 2
atomicValue = new XdmAtomicValue(getStringValue(fact));

getDoubleValue()

    String precision = fact.getDecimals();
    BigDecimal value = new BigDecimal(fact.getValue());
    if((precision != null ) && (precision.equals(INF_STRING) == false )){
        if(Integer.parseInt(precision)>0){
            NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
            DecimalFormat df = (DecimalFormat)nf;

            // If the decimal value is greater than 0, then we need the decimal precision correct to n places of decimal
            df.setMaximumFractionDigits(Integer.parseInt(precision) + 1);
            double doublePrecision = Math.pow(10,-Integer.parseInt(precision))/2;
            df.setMaximumFractionDigits(Integer.parseInt(precision) + 1);
            precision = df.format(doublePrecision);
            System.out.println("doublePrecision\t:\t"+doublePrecision);
            return (double) Math.round(value.doubleValue() * doublePrecision) / doublePrecision;
        }else{

            int scale = (int) Math.pow(10, -Integer.parseInt(precision));
            System.out.println("scale\t:\t"+scale);
            return (double) Math.round(value.doubleValue() * scale) / scale;

        }
    }
    return value.doubleValue();

在getStringValue()中

    String value = fact.getValue();
    String decimal = fact.getDecimals();
    String DOT = "\\.";
    if(value.contains(".")){
        final int parseInt = Integer.parseInt(decimal);
        if(parseInt>0){
            String[]split = value.split(DOT);
            value = split[0];
            if(parseInt>=value.length()){
                return "0";
            }
            for (int i = 0; i < parseInt; i++) {
                char[] array =value.toCharArray();
                array[value.length()-i-1]="0".charAt(0);
                value = new String(array);
            }
        }else{
            final int parseNegativeInt = -Integer.parseInt(decimal);
            String[]split = value.split(DOT);
            String tempValue = split[1];
            if(tempValue.length()>parseNegativeInt){
                tempValue = tempValue.substring(0, parseNegativeInt);
            }
            value = split[0]+"."+tempValue;
        }
    }
    return value;

当前实现和替代(2)不适用于上述规则,当我返回双精度时,它将大数字转换为包含字符 E 的表达式,例如5.12344E12,在其他规则中失败。

没有 systemId 的模块的第 199 行出现错误: FORG0001:无法将字符串“1.089563E9”转换为 xs:十进制:无效字符“E” 在 iaf:splitValueThreshold()(没有 systemId 的模块#20) 在 iaf:numeric-equal() (没有 systemId 的模块#343)

请提出任何其他选择。

【问题讨论】:

  • 嗯,你在哪里设置、构造或创建变量value,你是想在那儿传入一个字符串还是某个数字类型?
  • 您可以使用saxonica.com/html/documentation/dotnetdoc/Saxon/Api/… 在您的Java 代码中构造一个xs:decimal 并将其传递给setExternalVariable。或者,您可以在 XPath 端使用 if (xs:decimal($a) &gt; 0) ... 或按照答案建议使用 if (number($a) &gt; 0)...,尽管这会创建一个 xs:double。
  • 抱歉,我想我发布了一个指向 .NET API 的链接,Java API 位于 saxonica.com/html/documentation/javadoc/net/sf/saxon/s9api/…
  • 如果你的 Java 代码中没有数字类型,而是一个字符串,那么你可以使用saxonica.com/html/documentation/javadoc/net/sf/saxon/s9api/… 来构造某个数字类型
  • @MartinHonnen,我无法将 if 条件更改为业务规则,所以我猜你的第二条评论不起作用。将检查您分享的链接是否有任何帮助!

标签: java xml xquery saxon xbrl


【解决方案1】:

通常,XPath &gt; 将字符串操作数隐式转换为数字,但您可以使用 number() XPath 函数强制转换。

if (number($a) > 0) then (iaf:numeric-equal(iaf:numeric-multiply($b, $c), $d)) else (true())

【讨论】:

  • 我无法更改规则以添加number 功能。我尝试将值作为 double 传递,但如果该值太大而无法处理十进制,则在数字中包含“E”。并且此逻辑在数字中不包含“E”的其他规则中失败。请推荐!
  • 很遗憾,我无法更改规则。请找到我更新后的问题,因为我尝试了更多解决问题的方法。
【解决方案2】:

假设你在 Java 端有你的数值作为字符串,例如String value = "2179.125955"; 然后我建议将它们作为 xs:decimals 传递给 XQuery/XPath,方法是使用 new XdmAtomicValue(new BigDecimal(value)) 作为传递给 setExternalVariable 的值,例如

xqueryEvaluator.setExternalVariable(new QName(memberName), new XdmAtomicValue(new BigDecimal(value)));

【讨论】:

  • 我会试试这个解决方案,如果它有效,会告诉你!!
  • 一些在实施之前通过的规则已经开始失败,需要对此进行更多调试。感谢您的帮助!
【解决方案3】:

我赞同 Martin 的建议(我首先忽略了 BigDecimal 与 BigDecimalValue)。

根据 Saxon 的文档,我还想到了一些替代方案:

atomicValue = new XdmAtomicValue(
    new BigDecimalValue(getDoubleValue(fact))
);

或者为了避免使用双打或 BigDecimal,例如:

atomicValue = new XdmAtomicValue(
    (BigDecimalValue)BigDecimalValue.makeDecimalValue(getStringValue(fact), true)
);
// potentially adding an "instance of BigDecimalValue" check in the middle
// or bypassing all checks with 'false' instead of 'true'

注意:如果传递的是 xs:double 而不是 xs:decimal,我不确定我是否完全理解其他规则中出现的问题。我怀疑这些其他规则可能涉及到xs:string,因为这是可以引入E 的地方。任何类型的数值之间的 XPath 比较都应该是无缝的。

总的来说(但我只是在这里猜测,因为我不知道所涉及的细节,除了在规则中看到 EBA 的区间算术函数的用法),我认为对齐使用的类型可能是一个好主意 or使用原始 XBRL 概念类型传递给 XBRL 公式规则(使用 xs:decimal 代表 xbrli:decimalItemType (r) 或 xbrli:monetaryItemType (m),但 xs:double 代表 xbrli:doubleItemType 等),因为词法空间随后将匹配XBRL 实例中使用的那些。

【讨论】:

  • 由于这一变化,我的其他规则都失败了。正在调查。
  • 我使用了 BigDecimal,BigDecimalValue 类的包信息是什么?
  • 它是net.sf.saxon.value,也就是说,这是撒克逊人特有的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-11
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 2017-03-15
  • 2015-07-05
相关资源
最近更新 更多