Java 如何在ExtensionFunction Saxon HE 9.7中支持返回ArrayList
我有一个使用Saxon HE 9.7进行XML转换的程序Java 如何在ExtensionFunction Saxon HE 9.7中支持返回ArrayList,java,xslt,saxon,Java,Xslt,Saxon,我有一个使用Saxon HE 9.7进行XML转换的程序 public String transform() throws TransformerException { TransformerFactory factory = TransformerFactory.newInstance(); TransformerFactoryImpl tFactoryImpl = (TransformerFactoryImpl) factory; Configuration sax
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类:
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,即作为新XdmAtomicValue方法的方法getEmployee不将ArrayList作为构造函数参数。我将回答Saxon 9.9,因为这是您真正应该使用的版本。在Saxon 9.7中不存在XdmMap类,因此在该版本中传递Java和XSLT之间的映射将是困难或不可能的 首先需要确定要返回的XDM类型:我假设这可能是mapxs:string,xs:string*——这是一个映射序列,其中字符串作为键,字符串作为值 首先需要在getResultType方法中将其声明为结果类型。这可能足以做到:
public SequenceType getResultType() {
return SequenceType.makeSequenceType(ItemType.ANY_MAP, OccurrenceIndicator.ZERO_OR_MORE);
}
这可能不够精确,但提供更精确的结果类型除了让Saxon对函数实际返回的内容进行更仔细、更昂贵的检查之外,别无其他用处。如果您想提供更精确的返回类型,则必须使用ItemTypeFactory.newMapType….来构造它
然后调用方法需要返回此类型的实例
您需要将每个员工表示为一个XdmMap。有两种方法可以构造XdmMap
a您可以构建Java HashMap,然后使用静态方法XdmMap.makeMap对其进行转换
b您可以逐步构建地图:
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实例;原稿不变
最后,您需要构造这些XdmMap实例的序列。最简单的方法是构造一个包含所有映射的Java列表,然后使用新的XDMValueLiterable项将其转换为XdmValue。非常感谢。我使用了Saxon HE 9.9,并且能够将结果转换为XdmValue。但是,我想让getEmployeeName和getEmployee方法都可以访问。我需要为每个函数创建单独的类,还是可以将它们都放在一个类中?它们应该是单独的类-每个函数一个类。当使用列表项的值时,我遇到此错误:FOTY0013:无法原子化映射{name:john},映射{age:30}。我已经用xslt文件更新了这个问题。在xsl:variable中声明类型总是一个好主意:在本例中为=mapxs:string,xs:string,还是mapxs:string,xs:string*——一个映射序列?无论如何,将xsl:value应用于映射都是行不通的。您需要从映射中提取特定值,例如$list[1]?名称。