我很困惑为什么下面的示例程序拒绝正确应用我的样式表。看起来dyn:evaluate
Xalan 2.7.1 中拒绝处理某些 XPath 变量。
运行以下程序xalan-j
在类路径中产生以下结果:
package com.testing2.xslt;
import java.io.*;
import java.util.logging.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
public class DynEvaluateTransform {
private static final String XSLT = "" +
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n" +
" xmlns:det=\"org:example:DynEvaluateTransform\"\n" +
" xmlns:dyn=\"http://exslt.org/dynamic\"\n" +
" extension-element-prefixes=\"dyn\"\n" +
" version=\"1.0\">\n" +
" \n" +
" <xsl:variable name=\"input-doc\" select=\"document('input.xml', /)\" />\n" +
" <xsl:variable name=\"selections\" select=\"$input-doc/det:selections\" />\n" +
" \n" +
" <xsl:template match=\"/\">\n" +
" <xsl:choose>\n" +
" <xsl:when test=\"function-available('dyn:evaluate')\">\n" +
" <xsl:message>dyn:evaluate available</xsl:message>\n" +
" </xsl:when>\n" +
" <xsl:otherwise>\n" +
" <xsl:message>dyn:evaluate not available</xsl:message>\n" +
" </xsl:otherwise>\n" +
" </xsl:choose>\n" +
" <xsl:message>input.xml content:</xsl:message>\n" +
" <xsl:for-each select=\"$selections/*\">\n" +
" <xsl:message>{<xsl:value-of select=\"namespace-uri()\"/>}<xsl:value-of select=\"local-name()\"/></xsl:message>\n" +
" </xsl:for-each> \n" +
" <xsl:for-each select=\"//@condition\">\n" +
" <xsl:message><xsl:value-of select=\".\"/></xsl:message>\n" +
" <xsl:message><xsl:value-of select=\"string(dyn:evaluate(string(.)))\"/></xsl:message>\n" +
" </xsl:for-each>\n" +
" </xsl:template>\n" +
" \n" +
"</xsl:stylesheet>";
private static final String EXAMPLE = "" +
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<foos xmlns=\"org:example:DynEvaluateTransform\"> \n" +
" <foo condition=\"true()\" /> \n" +
" <foo condition=\"false()\" /> \n" +
" <foo condition=\"false() or true()\" />\n" +
" <foo condition=\"$selections\" />\n" +
" <foo condition=\"$selections/*\" />\n" +
" <foo condition=\"$selections/*[local-name()='a']\" />\n" +
" <foo condition=\"$selections/element::node()[local-name()='a']\" />\n" +
" <foo condition=\"local-name($selections/*)\" />\n" +
" <foo condition=\"not($selections/*[local-name()='a' and namespace-uri()='org:example:foo'])\" />\n" +
" <foo condition=\"$selections/*[local-name()='b' and namespace-uri()='org:example:foo']\" />\n" +
" <foo condition=\"$selections/*[local-name()='c' and namespace-uri()='org:example:foo']\" />\n" +
" <foo condition=\"not($selections/*[local-name()='a' and namespace-uri()='org:example:foo']) or ($selections/*[local-name()='b' and namespace-uri()='org:example:foo'] and $selections/*[local-name()='c' and namespace-uri()='org:example:foo'])\" />\n" +
"</foos>";
private static final String INPUT = "" +
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<selections xmlns=\"org:example:DynEvaluateTransform\">\n" +
" <a xmlns=\"org:example:foo\"/>\n" +
" <b xmlns=\"org:example:foo\"/>\n" +
" <c xmlns=\"org:example:foo\"/>\n" +
"</selections>";
private TransformerFactory xalanTransFact;
public DynEvaluateTransform() {
xalanTransFact = new org.apache.xalan.processor.TransformerFactoryImpl();
xalanTransFact.setURIResolver(new Resolver());
}
private void applyTransform() {
// XSLT(EXAMPLE) --> output.xml
// ^
// |
// INPUT
OutputStreamWriter writer = null;
try {
String outputFileName = DynEvaluateTransform.getLocalFileName("output.xml");
File file = new File(outputFileName);
writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
System.out.println(org.apache.xalan.Version.getVersion());
Transformer transformer = xalanTransFact.newTransformer(new StreamSource(new StringReader(XSLT)));
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
transformer.transform(
new StreamSource(new StringReader(EXAMPLE)),
new StreamResult(writer));
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
} catch (FileNotFoundException ex) {
Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
} catch (TransformerConfigurationException ex) {
Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
} catch (TransformerException ex) {
Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException ex) {
}
}
}
}
private void rebuildInput() {
// ignore - this just writes the input.xml file, so we can later reference it
StringReader strReader = null;
OutputStreamWriter fileWriter = null;
try {
String fileName = getLocalFileName("input.xml");
strReader = new StringReader(INPUT);
File file = new File(fileName);
fileWriter = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.transform(
new StreamSource(strReader),
new StreamResult(fileWriter));
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
} catch (FileNotFoundException ex) {
Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
} catch (TransformerConfigurationException ex) {
Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
} catch (TransformerException ex) {
Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(DynEvaluateTransform.class.getName()).log(Level.SEVERE, null, ex);
} finally {
if (strReader != null) {
strReader.close();
}
if (fileWriter != null) {
try {
fileWriter.close();
} catch (IOException ex) {
}
}
}
}
public static void main(String[] args) {
DynEvaluateTransform det = new DynEvaluateTransform();
det.rebuildInput();
det.applyTransform();
}
private static String getLocalFileName(String href) {
String name = System.getProperty("user.dir");
if (!name.endsWith(File.separator)) {
name += File.separator;
}
name += href;
return name;
}
private static class Resolver implements URIResolver {
@Override
public Source resolve(String href, String base) throws TransformerException {
if ("input.xml".equals(href)) {
return new StreamSource(new File(DynEvaluateTransform.getLocalFileName(href)));
} else {
return null;
}
}
}
}
Xalan Java 2.7.1
SystemId Unknown; Line #14; Column #30; dyn:evaluate available
SystemId Unknown; Line #20; Column #22; input.xml content:
SystemId Unknown; Line #22; Column #26; {org:example:foo}a
SystemId Unknown; Line #22; Column #26; {org:example:foo}b
SystemId Unknown; Line #22; Column #26; {org:example:foo}c
SystemId Unknown; Line #25; Column #26; true()
SystemId Unknown; Line #26; Column #26; true
SystemId Unknown; Line #25; Column #26; false()
SystemId Unknown; Line #26; Column #26; false
SystemId Unknown; Line #25; Column #26; false() or true()
SystemId Unknown; Line #26; Column #26; true
SystemId Unknown; Line #25; Column #26; $selections
SystemId Unknown; Line #26; Column #26;
SystemId Unknown; Line #25; Column #26; $selections/*
SystemId Unknown; Line #26; Column #26;
SystemId Unknown; Line #25; Column #26; $selections/*[local-name()='a']
SystemId Unknown; Line #26; Column #26;
SystemId Unknown; Line #25; Column #26; $selections/element::node()[local-name()='a']
SystemId Unknown; Line #26; Column #26;
SystemId Unknown; Line #25; Column #26; local-name($selections/*)
SystemId Unknown; Line #26; Column #26;
SystemId Unknown; Line #25; Column #26; not($selections/*[local-name()='a' and namespace-uri()='org:example:foo'])
SystemId Unknown; Line #26; Column #26; true
SystemId Unknown; Line #25; Column #26; $selections/*[local-name()='b' and namespace-uri()='org:example:foo']
SystemId Unknown; Line #26; Column #26;
SystemId Unknown; Line #25; Column #26; $selections/*[local-name()='c' and namespace-uri()='org:example:foo']
SystemId Unknown; Line #26; Column #26;
SystemId Unknown; Line #25; Column #26; not($selections/*[local-name()='a' and namespace-uri()='org:example:foo']) or ($selections/*[local-name()='b' and namespace-uri()='org:example:foo'] and $selections/*[local-name()='c' and namespace-uri()='org:example:foo'])
SystemId Unknown; Line #26; Column #26; true
示例程序使用提供的转换 (XSLT) 转换示例输入 (EXAMPLE),该转换采用输入文件 (INPUT、input.xml
),通过打开document()
函数,作为“参数”。该输入文件包含一组使用 XPath 表达式进行测试的元素(位于示例中)。
程序的输出表明dyn:evaluate
支持功能,即input.xml
如果正确读取,简单的 XPath 表达式可以正确计算,但是一旦涉及 XPath 变量,它就会中断。
以下涉及的所有文档的可读版本。
输入.xml
<?xml version="1.0" encoding="UTF-8"?>
<selections xmlns="org:example:DynEvaluateTransform">
<a xmlns="org:example:foo"/>
<b xmlns="org:example:foo"/>
<c xmlns="org:example:foo"/>
</selections>
EXAMPLE
<?xml version="1.0" encoding="UTF-8"?>
<foos xmlns="org:example:DynEvaluateTransform">
<foo condition="true()" />
<foo condition="false()" />
<foo condition="false() or true()" />
<foo condition="$selections" />
<foo condition="$selections/*" />
<foo condition="$selections/*[local-name()='a']" />
<foo condition="$selections/element::node()[local-name()='a']" />
<foo condition="local-name($selections/*)" />
<foo condition="not($selections/*[local-name()='a' and namespace-uri()='org:example:foo'])" />
<foo condition="$selections/*[local-name()='b' and namespace-uri()='org:example:foo']" />
<foo condition="$selections/*[local-name()='c' and namespace-uri()='org:example:foo']" />
<foo condition="not($selections/*[local-name()='a' and namespace-uri()='org:example:foo']) or ($selections/*[local-name()='b' and namespace-uri()='org:example:foo'] and $selections/*[local-name()='c' and namespace-uri()='org:example:foo'])" />
</foos>
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:det="org:example:DynEvaluateTransform"
xmlns:dyn="http://exslt.org/dynamic"
extension-element-prefixes="dyn"
version="1.0">
<xsl:variable name="input-doc" select="document('input.xml', /)" />
<xsl:variable name="selections" select="$input-doc/det:selections" />
<xsl:template match="/">
<xsl:choose>
<xsl:when test="function-available('dyn:evaluate')">
<xsl:message>dyn:evaluate available</xsl:message>
</xsl:when>
<xsl:otherwise>
<xsl:message>dyn:evaluate not available</xsl:message>
</xsl:otherwise>
</xsl:choose>
<xsl:message>input.xml content:</xsl:message>
<xsl:for-each select="$selections/*">
<xsl:message>{<xsl:value-of select="namespace-uri()"/>}<xsl:value-of select="local-name()"/></xsl:message>
</xsl:for-each>
<xsl:for-each select="//@condition">
<xsl:message><xsl:value-of select="."/></xsl:message>
<xsl:message><xsl:value-of select="string(dyn:evaluate(string(.)))"/></xsl:message>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Xalan 是否不支持 XPath 变量dyn:evaluate
争论?我是否正确定义了表达式?报告称,尝试在选择 Xalan 的情况下在 oXygen 中运行此样式表java.lang.RuntimeException: ElemTemplateElement error: Function not supported!
当第一次遇到 XPath 变量时。
Edit:
我重写了这个问题,以澄清我的实际问题是什么。