Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从JTextArea中的xsl文件打印“”_Java_Xml_Xslt - Fatal编程技术网

Java 从JTextArea中的xsl文件打印“”

Java 从JTextArea中的xsl文件打印“”,java,xml,xslt,Java,Xml,Xslt,我总是试图在JTextArea中打印xsl消息。使用上一个问题的代码,我可以在文本区域打印xsl输出,但不能打印xslt文件中编写的消息 Java代码: public static void xslTransform(File xmlFile)throws IOException, TransformerException{ File xslFile = ...; StreamSource xmlSource = new StreamSource(xmlFile); StreamSource x

我总是试图在JTextArea中打印xsl消息。使用上一个问题的代码,我可以在文本区域打印xsl输出,但不能打印xslt文件中编写的消息

Java代码:

public static void xslTransform(File xmlFile)throws IOException, TransformerException{
File xslFile = ...;
StreamSource xmlSource = new StreamSource(xmlFile);
StreamSource xslSource = new StreamSource(xslFile);
StreamResult result = new StreamResult (new StringWriter()); //maybe here is the problem?
TransformerFactory transformerFact = TransformerFactory.newInstance();
transformerFact.setAttribute(FeatureKeys.MESSAGE_EMITTER_CLASS, "MyMessageEmitter");
Transformer transformer = transformerFact.newTransformer(xslSource);
transformer.transform(xmlSource,result);
}


public class MyMessageEmitter extends net.sf.saxon.serialize.MessageEmitter{
String message;
private StringWriter stwriter = new StringWriter();
public void MyMessageEmitter() throws XPathException{
setWriter(stwriter);
}
@Override
public void close() throws XPathException{
super.close();
message=stwriter.toString();
myJTextArea.setText(message);
stwriter = new StringWriter();
}
}
XSLT文件:

<xsl:template match="/">
<xsl:for-each select="//@id">
<xsl:message>
<xsl:value-of select="name(parent::*)"/> <xsl:text></xsl:text><xsl:value-of select="."/>
</xslmessage>
</xsl:for-each>
</xsl:tempate>
对于此代码,来自java的消息为空,因为此xslt不会粘贴任何输出,例如新的xml文档。我用另一个打印新xml的xslt检查了这一点

那么,如何获取打印xslt的消息呢

谢谢你的帮助
KaFu

如果MyMessageEmitter有一个对myJTextArea的引用,那么它可能是一个内部类

这意味着它的全名不是MyMessageEmitter,而是更复杂的东西。根据您编写的代码,我得到以下信息:

错误 未能加载MyMessageEmitter net.sf.saxon.trans.XPathException:未能加载MyMessageEmitter net.sf.saxon.trans.DynamicLoader.getClassDynamicLoader.java:123 ... 原因:java.lang.ClassNotFoundException:MyMessageEmitter

如果将factory.setAttribute中的类名更改为正确的名称,则会得到以下结果:

错误 未能实例化类jaxptest.TransformMessageTest$MyMessageEmitter net.sf.saxon.trans.XPathException:未能实例化类jaxptest.TransformMessageTest$MyMessageEmitter net.sf.saxon.trans.DynamicLoader.getInstanceDynamicLoader.java:185 ... 原因:java.lang.InstanceException:jaxptest.TransformMessageTest$MyMessageEmitter

这是因为非静态内部类只能从其包含类实例化

你的下一个错误很微妙,我花了很长时间才诊断出来。你已经写信了

public void MyMessageEmitter() throws XPathException{ 
  setWriter(stwriter);
}
但这使MyMessageEmitter成为一个普通的方法,而您希望它是一个构造函数。所以应该写下:

public MyMessageEmitter() throws XPathException{ 
  setWriter(stwriter);
}
如果我将内部类设置为静态,它就会工作;但现在的问题是静态类不能简单地按名称引用jTextArea

下一个问题也是相当微妙的,这一次至少要归咎于Saxon:MessageEmitter上的close方法被调用了两次。不幸的是,当发生这种情况时,第一个调用会创建一个新的空StringWriter,第二个调用会将此空StringWriter的内容写入文本区域。因此,我将其更改为在open方法中而不是在close方法中创建新的StringWriter

现在剩下的问题是如何在MessageEmitter和JTextArea之间通信。这不是小事。我是通过让MessageEmitter写入一个静态变量,并让调用应用程序拾取这个静态变量来实现的。但显然,在生产应用程序中使用全局静态变量是不可接受的。问题是Saxon创建了MessageEmitter类的实例,但没有提供任何直接的通信方式。我能找到的唯一解决方案是使用一些较低级别的Saxon接口,如:

public void testMessageCapture() {
        try {
            String stylesheet =
                "<?xml version='1.0'?>" +
                    "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" +
                    "    version='2.0'>" +
                    "  <xsl:template match='/'>" +
                    "<first/>" +
                    "<xsl:message>Hi!</xsl:message>" +
                    "  </xsl:template>" +
                    "</xsl:stylesheet>";

            TransformerFactory transFactory = new TransformerFactoryImpl();
            //transFactory.setAttribute(FeatureKeys.MESSAGE_EMITTER_CLASS, "jaxptest.TransformMessageTest$MyMessageEmitter");

            Templates templates = transFactory.newTemplates(
                new SAXSource(new InputSource(new StringReader(stylesheet))));


            StreamResult result = new StreamResult(new StringWriter());
            final StringWriter messageOut = new StringWriter();
            Transformer transformer = templates.newTransformer();
            ((net.sf.saxon.jaxp.TransformerImpl)transformer).getUnderlyingController().setMessageEmitter(
                new MessageEmitter() {
                    @Override
                    public void open() throws XPathException {
                        setWriter(messageOut);
                        super.open();
                    }
                }
            );
            transformer.transform(new StreamSource(new StringReader("<in/>")), result);
            assertEquals("Hi!", messageOut.toString().trim());
        } catch (TransformerException e) {
            e.printStackTrace();
            fail();
        }
    }
当然,您可以将对字符串编写器的写入替换为对JTextArea的直接写入

这段代码实际上是特定于Saxon 9.6的;在早期版本中,您将直接将JAXP转换器转换为控制器


这恰恰说明了依赖JAXP接口的局限性。使用Saxon的原生s9api接口将更容易做到这一点。

我明白了。。。以下是解决方案:

Processor proc = new Processor(false);
XsltCompiler comp = new proc.newXsltCompiler();
StreamSource styleSource = new StreamSource(xsltFile);
StreamSource xmlSource = new StreamSource(xmlFile);
String msg="";
XsltExecutable templates = comp.compile(styleSource);
XsltTransformer transformer = templates.load();
transformer.setSource(xmlSource);
transformer.setMessageListener(new MessageListener(){
@Override
public void message (XdmNode content, boolean terminate, SourceLocator locator){
try{
if (content.getTypedValue!= null){
msg += content.getTypedValue().toString() + "\n";
}}
catch (SaxonApiException ex){
Logger.getLogger(...);
}
}
});
Writer write = new StringWriter();
Serializer out = proc.newSerializer(write);
transformer.setDestination(out);
transformer.transform();
textAreaOut.setText(msg);

谢谢你的帮助

你不能。希望它会出现在您的控制台日志中。不构成输出的一部分。myJTextArea在哪里声明?如果您想捕获所有消息,我希望调用myJTextArea.appendmessage。@LingamurthyCS是的,它存在于我的控制台日志中……这就是我在textarea@MartinHonnen谢谢,我忘了粘贴声明,但它是声明的=