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

时间:2018-03-28 12:52:05

标签: java xml xquery saxon xbrl

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

执行此操作的代码段为:

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)不适用于上述规则,当我返回double时,它会将大数字转换为包含char E 的表达式,例如5.12344E12,在其他规则中失败。

  

模块的第199行出现错误,没有systemId :     FORG0001:无法转换字符串&#34; 1.089563E9&#34;到xs:decimal:无效字符&#39; E&#39;     at iaf:splitValueThreshold()(模块没有systemId #20)     at iaf:numeric-equal()(模块没有systemId #343)

请建议任何其他选择。

3 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:2)

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

$test_connection

答案 2 :(得分:1)

我是马丁的第二个建议(我首先忽略了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的区间运算函数的使用),我认为对齐或使用的类型可能是一个不错的主意。使用原始XBRL概念类型传递给XBRL公式规则(对xs:decimal(r)或xbrli:decimalItemType(m)使用xbrli:monetaryItemTypexs:double使用xbrli:doubleItemType,等等,因为词汇空间将匹配XBRL实例中使用的那些。