简体   繁体   English

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

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

I have created a function using the Saxon documentation which has 3 parameters.我使用具有 3 个参数的撒克逊文档创建了 function。 The function takes an input string and pads it out to a specific size using an integer and string values. function 获取输入字符串并使用 integer 和字符串值将其填充到特定大小。

padStringLeft(inputStr,size,padChar) padStringLeft(inputStr,大小,padChar)

If I put this in my XSLT and hard wire the parameters the function works.如果我把它放在我的 XSLT 中并硬连接 function 的参数。

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

The output from the above would be '0001'上面的 output 将是“0001”

When I pass the contents of a XSLT variable however and set a debug / break point in my java function I can see that I'm getting param0 as a lazysequence.但是,当我传递 XSLT 变量的内容并在我的 java function 中设置调试/断点时,我可以看到我正在获取参数序列。

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

Java function Java function

As my code is attempting to treat it as a string it does not work.由于我的代码试图将其视为字符串,因此它不起作用。

How should I be handling this scenario, how do I access the value or the xsl-variable/param and what if sometimes I want to use a literal string instead of a variable?我应该如何处理这种情况,如何访问值或 xsl 变量/参数,如果有时我想使用文字字符串而不是变量怎么办?

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);
                }
            };
    }

}

Thanks谢谢

Dave戴夫

In general the parameters are passed as instance of the class net.sf.saxon.om.Sequence , and you should only use the methods on the interface Sequence , rather than examining what particular kind of Sequence it is, because that could change in the future.通常,参数作为 class net.sf.saxon.om.Sequence的实例传递,您应该只使用接口Sequence上的方法,而不是检查它是什么特定类型的Sequence ,因为这可能会在未来。

If you're expecting a singleton sequence (that is, a single item), call head() to get the first item in the sequence (this will return null if the sequence is empty).如果您期望 singleton 序列(即单个项目),请调用head()以获取序列中的第一项(如果序列为空,这将返回 null)。 You will then have an instance of net.sf.saxon.om.Item .然后,您将拥有一个net.sf.saxon.om.Item实例。 (The Sequence might already be an Item , because an item is a sequence, but you can't rely on that, and calling head() is safer than casting.) If you're expecting a string, you can safely call getStringValue() on this item to get the value as a string. Sequence可能已经是一个Item ,因为一个项目是一个序列,但你不能依赖它,调用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.另请注意,Saxon 尽可能使用惰性求值,这意味着在有人询问它的值之前可能不会实际计算字符串。 This means that innocent-looking calls like head() and getStringValue() can actually throw exceptions, and you need to be prepared for this.这意味着像head()getStringValue()这样看似无辜的调用实际上可能会引发异常,您需要为此做好准备。

So in short, you should replace所以简而言之,你应该更换

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

with

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.另请注意,Saxon 尽可能使用惰性求值,这意味着在有人询问它的值之前可能不会实际计算字符串。 This means that innocent-looking calls like head() and getStringValue() can actually throw exceptions, and you need to be prepared for this.这意味着像 head() 和 getStringValue() 这样看似无辜的调用实际上可能会引发异常,您需要为此做好准备。

So if I understand you correctly - when I call Transform to process the XSLT transformation it will call each of my custom java external functions as needed but the reference to因此,如果我理解正确 - 当我调用 Transform 来处理 XSLT 转换时,它将根据需要调用我的每个自定义 java 外部函数,但参考

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

could generate an exception?会产生异常吗?

I would then need to do something within the java function to force it to get the value - or would I let the exception propogate back to the calling Transformation and catch it there?然后我需要在 java function 中做一些事情来强制它获取值 - 或者我会让异常传播回调用 Transformation 并在那里捕获它?

Dave戴夫

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM