如何在 ExtensionFunction Saxon HE 9.7 中支持返回 ArrayList [英] How to support returning ArrayList in ExtensionFunction Saxon HE 9.7

查看:48
本文介绍了如何在 ExtensionFunction Saxon HE 9.7 中支持返回 ArrayList的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用 Saxon HE 9.7 进行 XML 转换的程序.

I have a program that uses Saxon HE 9.7 for XML transformation.

public String transform() throws TransformerException {
    TransformerFactory factory = TransformerFactory.newInstance();
    TransformerFactoryImpl tFactoryImpl = (TransformerFactoryImpl) factory;

    Configuration saxonConfig = tFactoryImpl.getConfiguration();
    Processor processor = (Processor) saxonConfig.getProcessor();

    processor.registerExtensionFunction(new Employee());

    Source xslt = new StreamSource(new File("mappings.xslt"));
    Transformer transformer = factory.newTransformer(xslt);

    Source text = new StreamSource(new File("payload.xml"));
    transformer.transform(text, new StreamResult(sw));
    return sw.toString();
}

ExtensionFunction 类:

The ExtensionFunction class:

public class Employee implements ExtensionFunction {

private List<HashMap<String, String>> employee = new ArrayList<HashMap<String, String>>();
private String employeeName = "John";

public List<HashMap<String, String>> getEmployee() {
    HashMap<String, String> map1 = new HashMap<>();
    map1.put("name", "john");
    HashMap<String, String> map2 = new HashMap<>();
    map2.put("age", "30");
    employee.add(map1);
    employee.add(map2);
    return employee;
}

public String getEmployeeName(){
    return employeeName;
}

@Override
public XdmValue call(XdmValue[] arg0) throws SaxonApiException {
    return new XdmAtomicValue(getEmployeeName());
}

@Override
public SequenceType[] getArgumentTypes() {
    return new SequenceType[] {};
}

@Override
public QName getName() {
    return new QName("test.extension.Employee", "getEmployeeName");
}

@Override
public SequenceType getResultType() {
    return SequenceType.makeSequenceType(ItemType.STRING, OccurrenceIndicator.ONE);
}

XSLT 文件:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0" xmlns:Employee="test.extension.Employee" 
xmlns:saxon="http://saxon.sf.net/">
<xsl:output method="xml" indent="yes" />
<xsl:variable name="list" 
select="Employee.getEmployee()" />
<xsl:variable name="count" select="count($list)" />
<xsl:template match="/">
    <company>
            <employee>
                <xsl:attribute name="name">
                    <xsl:value-of select="$list[1]" />
                </xsl:attribute>
            </employee>
    </company>
</xsl:template>
</xsl:stylesheet>   

目前,我可以调用从 xslt 返回字符串的 getEmployeeName 方法.但是如何修改 Employee 类以支持返回 HasMap 的 ArrayList,即方法 getEmployee() 作为新的 XdmAtomicValue() 方法不接受 ArrayList 作为构造函数参数.

Currently, I am able to call getEmployeeName method that returns a String from xslt. But how do I modify Employee class to also support returning ArrayList of HasMap i.e the method getEmployee() as the new XdmAtomicValue() method doesn't takes ArrayList as constructor argument.

推荐答案

我将回答 Saxon 9.9,因为那是您真正应该使用的版本.XdmMap 类在 Saxon 9.7 中不存在,因此该版本在 Java 和 XSLT 之间传递映射将变得困难或不可能.

I'm going to answer for Saxon 9.9, because that's the release you should really be using. The XdmMap class isn't present in Saxon 9.7, so passing maps between Java and XSLT with that release is going to be difficult or impossible.

您首先需要决定要返回的 XDM 类型:我假设这可能是 map(xs:string, xs:string)* - 这是一个带有字符串的映射序列作为键和字符串作为值.

You first need to decide what XDM type you want to return: I assume this is probably map(xs:string, xs:string)* - that is a sequence of maps with strings as the key and strings as the value.

您首先需要在 getResultType() 方法中将其声明为结果类型.这样做可能已经足够了:

You first need to declare this as the result type in your getResultType() method. It's probably good enough to do:

public SequenceType getResultType() {
    return SequenceType.makeSequenceType(ItemType.ANY_MAP, OccurrenceIndicator.ZERO_OR_MORE);
}

这并不像它想象的那么精确,但是提供更精确的结果类型除了使 Saxon 对函数实际返回的内容进行更仔细(且代价高昂)的检查之外不会实现任何其他目的.如果您想提供更精确的返回类型,则必须使用 ItemTypeFactory.newMapType(...) 构造它.

That's not quite as precise as it might be, but supplying a more precise result type isn't going to achieve anything other than causing Saxon to do more careful (and expensive) checking of what the function actually returns. If you wanted to provide a more precise return type you would have to construct it using ItemTypeFactory.newMapType(...).

那么你的 call() 方法需要返回一个这种类型的实例.

Then your call() method needs to return an instance of this type.

您需要将每个员工表示为一个 XdmMap.有两种方法可以构建 XdmMap.

You'll want to represent each Employee as an XdmMap. There are two ways you can construct the XdmMap.

(a) 您可以构建一个 Java HashMap,然后使用静态方法 XdmMap.makeMap()

(a) You could build a Java HashMap<String, String> and then convert it using the static method XdmMap.makeMap()

(b) 您可以逐步构建地图:

(b) You could construct the map incrementally:

XdmMap map = new XdmMap();
map = map.put(new XdmAtomicValue("name"), new XdmAtomicValue("John Doe"));
map = map.put(new XdmAtomicValue("age"), new XdmAtomicValue("24"));

等等.请注意,XdmMap 是不可变的,因此每个 put() 操作都会创建一个新的 XdmMap 实例;原作不变.

etc. Note that XdmMap is immutable so each put() operation creates a new XdmMap instance; the original is unchanged.

最后,您需要构造这些 XdmMap 实例的序列.最简单的方法是构造一个包含所有映射的 Java List,然后使用 new XdmValue(Iterable<...> 项目).

Finally, you need to construct a sequence of these XdmMap instances. The simplest way is to construct a Java List<XdmMap> containing all the maps, and then convert this to an XdmValue using new XdmValue(Iterable<...> items).

这篇关于如何在 ExtensionFunction Saxon HE 9.7 中支持返回 ArrayList的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆