Saxon-HE Java 扩展 - 如何访问作为参数传递的 xsl 变量的值?

Saxon-HE Java Extension - How to I access the value of a xsl-variable which is passed as a parameter?

我使用具有 3 个参数的 Saxon 文档创建了一个函数。该函数接受一个输入字符串并使用整数和字符串值将其填充到特定大小。

padStringLeft(inputStr,size,padChar)

如果我将其放入我的 XSLT 中并硬连接参数,该函数将起作用。

<debug1><xsl:value-of select="c4j_XSLT_Ext_padStringLeft:padStringLeft('1',4,'0')" /></debug1>

上面的输出是'0001'

然而,当我传递 XSLT 变量的内容并在我的 java 函数中设置调试/断点时,我可以看到我将 param0 作为惰性序列获取。

<debug2><xsl:value-of select="c4j_XSLT_Ext_padStringLeft:padStringLeft($myvar,4,'0')" /></debug2>

Java function

由于我的代码试图将其视为字符串,因此它不起作用。

我应该如何处理这种情况,如何访问值或 xsl-variable/param 以及如果有时我想使用文字字符串而不是变量怎么办?

public class XSLT_Ext_padStringLeft extends ExtensionFunctionDefinition
{

    @Override
    public SequenceType[] getArgumentTypes()
    {
        return new SequenceType[]{SequenceType.SINGLE_STRING,SequenceType.SINGLE_INTEGER, SequenceType.SINGLE_STRING};
    }

    @Override
    public StructuredQName getFunctionQName()
    {
        return new StructuredQName("c4j_XSLT_Ext_padStringLeft", "http://com.commander4j.Transformation.XSLT_Ext_padStringLeft", "padStringLeft");
    }

    @Override
    public SequenceType getResultType(SequenceType[] arg0)
    {
         return SequenceType.SINGLE_STRING;
    }

    @Override
    public ExtensionFunctionCall makeCallExpression()
    {
           return new ExtensionFunctionCall() {
                @Override
                public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
                    
                    String inputStr;
                    try
                    {
                        inputStr = ((StringValue)arguments[0]).getStringValue();
                    } catch (ClassCastException ex)
                    {
                       inputStr = "";   
                    }

                    
                    long size;
                    try
                    {
                        String temp =arguments[1].toString();
                        size = Integer.valueOf(temp);
                    } catch (ClassCastException ex)
                    {
                        size = 1;   
                    }
                    
                    String padStr;
                    try
                    {
                        padStr = ((StringValue)arguments[2]).getStringValue();
                    } catch (ClassCastException ex)
                    {
                        padStr = "";    
                    }
                    
                    String result = inputStr;
                    
                    while (result.length() < size)
                    {
                        result = padStr + result;
                    }

                    return StringValue.makeStringValue(result);
                }
            };
    }

}

谢谢

戴夫

一般来说,参数是作为 class net.sf.saxon.om.Sequence 的实例传递的,您应该只使用接口 Sequence 上的方法,而不是检查特定类型的 Sequence 是的,因为将来可能会改变。

如果您需要一个单例序列(即单个项目),请调用 head() 以获取序列中的第一个项目(如果序列为空,则 return null ).然后您将拥有 net.sf.saxon.om.Item 的实例。 (Sequence 可能已经是一个 Item,因为一个项目是一个序列,但你不能依赖它,调用 head() 比转换更安全。)如果你是需要一个字符串,您可以安全地调用此项目的 getStringValue() 以获取字符串形式的值。

另请注意,Saxon 尽可能使用惰性求值,这意味着在有人询问其值之前,可能不会实际计算字符串。这意味着像 head()getStringValue() 这样看似无害的调用实际上可能会抛出异常,您需要为此做好准备。

所以简而言之,你应该更换

inputStr = ((StringValue)arguments[0]).getStringValue();

inputStr = arguments[0].head().getStringValue();

Also note, Saxon uses lazy evaluation wherever possible, which means that the string might not actually be computed until someone asks for its value. This means that innocent-looking calls like head() and getStringValue() can actually throw exceptions, and you need to be prepared for this.

因此,如果我理解正确的话 - 当我调用 Transform 来处理 XSLT 转换时,它将根据需要调用我的每个自定义 java 外部函数,但对

的引用

inputStr = arguments[0].head().getStringValue();

会产生异常吗?

然后我需要在 java 函数中做一些事情来强制它获取值 - 或者我会让异常传播回调用转换并在那里捕获它?

戴夫