2017-01-31 29 views
0

Xalan 2.7.1で拡張関数に提供されたコンテキスト内のXPath式を評価しようとしています。なんらかの理由で、これは常にXalanの内部例外で失敗します。Xalan拡張関数の実装でXPath式を評価するにはどうすればよいですか?

注:これを実行するには、クラスパスにxalan-jが必要です。

package org.example; 

import java.io.*; 
import java.util.*; 
import java.util.logging.*; 
import javax.xml.namespace.NamespaceContext; 
import javax.xml.transform.*; 
import javax.xml.transform.stream.*; 
import javax.xml.xpath.*; 
import org.w3c.dom.*; 
import org.w3c.dom.traversal.NodeIterator; 
import org.apache.xalan.extensions.ExpressionContext; 

public class XalanExtension { 

    public static final String NS = "org:example:foo"; 

    public static final String XSLT = "" + 
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 
"<xsl:stylesheet \n" + 
" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n" + 
" xmlns:foo=\"org:example:foo\"\n" + 
" xmlns:fun=\"xalan://org.example.XalanExtension\"\n" + 
" version=\"1.0\"> \n" + 
" \n" + 
" <xsl:template match=\"*|@*\">\n" + 
"  <xsl:apply-templates select=\"*|@*\"/>\n" + 
" </xsl:template>\n" + 
" \n" + 
" <xsl:template match=\"foo:test\">\n" + 
"  <xsl:variable name=\"result\" select=\"fun:evaluate(.)\"/>\n" + 
"  <xsl:message>\n" + 
"   Test: <xsl:value-of select=\".\"/> Result: <xsl:value-of select=\"$result\"/>\n" + 
"  </xsl:message>\n" + 
" </xsl:template>\n" + 
" \n" + 
"</xsl:stylesheet>"; 

    public static final String XML = "" + 
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + 
"<tests xmlns=\"org:example:foo\">\n" + 
" <a>1</a>\n" + 
" <b>2</b>\n" + 
" <c>3</c>\n" + 
" <test>../foo:a &gt; 5</test>\n" + 
"</tests>"; 

    private TransformerFactory xalanTransFact; 

    public XalanExtension() { 
     xalanTransFact = new org.apache.xalan.processor.TransformerFactoryImpl(); 
    } 

    public void transform() { 
     try { 
      StringWriter writer; 

      writer = new StringWriter(); 

      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, "text"); 
      transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8"); 

      transformer.transform(
        new StreamSource(new StringReader(XML)), 
        new StreamResult(writer)); 

      System.out.println(writer.toString()); 
     } catch (TransformerConfigurationException ex) { 
      Logger.getLogger(XalanExtension.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (TransformerException ex) { 
      Logger.getLogger(XalanExtension.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 

    public static void main(String[] args) { 
     XalanExtension instance = new XalanExtension(); 
     instance.transform(); 
    } 

    public static final NodeList evaluate(ExpressionContext ctx, NodeIterator nodes) { 
     // first node in document order 
     Node node = nodes.nextNode(); 
     if (node != null && node.hasChildNodes()) { 
      try { 
       String xpathExpression = node.getFirstChild().getNodeValue(); 

       XPathFactory xpathFactory = XPathFactory.newInstance(); 
       XPath xpath = xpathFactory.newXPath(); 
       xpath.setNamespaceContext(new NamespaceContext() { 
        @Override 
        public String getNamespaceURI(String prefix) { 
         if ("foo".equals(prefix)) { 
          return NS; 
         } 
         return null; 
        } 

        @Override 
        public String getPrefix(String namespaceURI) { 
         if (NS.equals(namespaceURI)) { 
          return "foo"; 
         } 
         return null; 
        } 

        @Override 
        public Iterator getPrefixes(String namespaceURI) { 
         return null; 
        } 
       }); 

       return (NodeList) xpath.evaluate(xpathExpression, ctx.getContextNode(), XPathConstants.NODESET); 
      } catch (XPathExpressionException ex) { 
       Logger.getLogger(XalanExtension.class.getName()).log(Level.SEVERE, "xpath evaluation failed", ex); 
      } 
     } 
     return null; 
    } 
} 

org.example.XalanExtension.evaluate(ExpressionContext, NodeIterator)に拡張機能が実装されています。これはXalanによって呼び出されますが、使用しているXPath評価コードは機能しません。このプログラムは、実際にはXPath式である既知の値を持つ特定の要素を見つけます。この要素は、表示されるコンテキストで評価されます。

I取得プログラムからの次の出力:

Xalan Java 2.7.1 
jan. 31, 2017 3:09:10 PM org.example.XalanExtension evaluate 
SEVERE: xpath evaluation failed 

javax.xml.transform.TransformerException: Unknown error in XPath. 
    at org.apache.xpath.XPath.execute(XPath.java:365) 
    at org.apache.xpath.XPath.execute(XPath.java:303) 
    at org.apache.xpath.jaxp.XPathImpl.eval(XPathImpl.java:216) 
    at org.apache.xpath.jaxp.XPathImpl.evaluate(XPathImpl.java:281) 
    at org.example.XalanExtension.evaluate(XalanExtension.java:116) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at org.apache.xalan.extensions.ExtensionHandlerJavaClass.callFunction(ExtensionHandlerJavaClass.java:367) 
    at org.apache.xalan.extensions.ExtensionHandlerJavaClass.callFunction(ExtensionHandlerJavaClass.java:440) 
    at org.apache.xalan.extensions.ExtensionsTable.extFunction(ExtensionsTable.java:222) 
    at org.apache.xalan.transformer.TransformerImpl.extFunction(TransformerImpl.java:473) 
    at org.apache.xpath.functions.FuncExtFunction.execute(FuncExtFunction.java:208) 
    at org.apache.xpath.XPath.execute(XPath.java:337) 
    at org.apache.xalan.templates.ElemVariable.getValue(ElemVariable.java:280) 
    at org.apache.xalan.templates.ElemVariable.execute(ElemVariable.java:248) 
    at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) 
    at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) 
    at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) 
    at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) 
    at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2400) 
    at org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(TransformerImpl.java:2270) 
    at org.apache.xalan.transformer.TransformerImpl.transformNode(TransformerImpl.java:1356) 
    at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:709) 
    at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1273) 
    at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1251) 
    at org.example.XalanExtension.transform(XalanExtension.java:67) 
    at org.example.XalanExtension.main(XalanExtension.java:81) 
Caused by: java.lang.NullPointerException 
    at org.apache.xpath.axes.AxesWalker.setRoot(AxesWalker.java:221) 
    at org.apache.xpath.axes.ReverseAxesWalker.setRoot(ReverseAxesWalker.java:53) 
    at org.apache.xpath.axes.WalkingIterator.setRoot(WalkingIterator.java:157) 
    at org.apache.xpath.axes.NodeSequence.setRoot(NodeSequence.java:265) 
    at org.apache.xpath.axes.LocPathIterator.execute(LocPathIterator.java:212) 
    at org.apache.xpath.Expression.execute(Expression.java:155) 
    at org.apache.xpath.operations.Operation.execute(Operation.java:109) 
    at org.apache.xpath.XPath.execute(XPath.java:337) 
    ... 28 more 
--------- 
java.lang.NullPointerException 
    at org.apache.xpath.axes.AxesWalker.setRoot(AxesWalker.java:221) 
    at org.apache.xpath.axes.ReverseAxesWalker.setRoot(ReverseAxesWalker.java:53) 
    at org.apache.xpath.axes.WalkingIterator.setRoot(WalkingIterator.java:157) 
    at org.apache.xpath.axes.NodeSequence.setRoot(NodeSequence.java:265) 
    at org.apache.xpath.axes.LocPathIterator.execute(LocPathIterator.java:212) 
    at org.apache.xpath.Expression.execute(Expression.java:155) 
    at org.apache.xpath.operations.Operation.execute(Operation.java:109) 
    at org.apache.xpath.XPath.execute(XPath.java:337) 
    at org.apache.xpath.XPath.execute(XPath.java:303) 
    at org.apache.xpath.jaxp.XPathImpl.eval(XPathImpl.java:216) 
    at org.apache.xpath.jaxp.XPathImpl.evaluate(XPathImpl.java:281) 
    at org.example.XalanExtension.evaluate(XalanExtension.java:116) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at org.apache.xalan.extensions.ExtensionHandlerJavaClass.callFunction(ExtensionHandlerJavaClass.java:367) 
    at org.apache.xalan.extensions.ExtensionHandlerJavaClass.callFunction(ExtensionHandlerJavaClass.java:440) 
    at org.apache.xalan.extensions.ExtensionsTable.extFunction(ExtensionsTable.java:222) 
    at org.apache.xalan.transformer.TransformerImpl.extFunction(TransformerImpl.java:473) 
    at org.apache.xpath.functions.FuncExtFunction.execute(FuncExtFunction.java:208) 
    at org.apache.xpath.XPath.execute(XPath.java:337) 
    at org.apache.xalan.templates.ElemVariable.getValue(ElemVariable.java:280) 
    at org.apache.xalan.templates.ElemVariable.execute(ElemVariable.java:248) 
    at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) 
    at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) 
    at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) 
    at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) 
    at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2400) 
    at org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(TransformerImpl.java:2270) 
    at org.apache.xalan.transformer.TransformerImpl.transformNode(TransformerImpl.java:1356) 
    at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:709) 
    at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1273) 
    at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1251) 
    at org.example.XalanExtension.transform(XalanExtension.java:67) 
    at org.example.XalanExtension.main(XalanExtension.java:81) 
--------------- linked to ------------------ 
javax.xml.xpath.XPathExpressionException: javax.xml.transform.TransformerException: Unknown error in XPath. 

    at org.apache.xpath.jaxp.XPathImpl.evaluate(XPathImpl.java:295) 
    at org.example.XalanExtension.evaluate(XalanExtension.java:116) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at org.apache.xalan.extensions.ExtensionHandlerJavaClass.callFunction(ExtensionHandlerJavaClass.java:367) 
    at org.apache.xalan.extensions.ExtensionHandlerJavaClass.callFunction(ExtensionHandlerJavaClass.java:440) 
    at org.apache.xalan.extensions.ExtensionsTable.extFunction(ExtensionsTable.java:222) 
    at org.apache.xalan.transformer.TransformerImpl.extFunction(TransformerImpl.java:473) 
    at org.apache.xpath.functions.FuncExtFunction.execute(FuncExtFunction.java:208) 
    at org.apache.xpath.XPath.execute(XPath.java:337) 
    at org.apache.xalan.templates.ElemVariable.getValue(ElemVariable.java:280) 
    at org.apache.xalan.templates.ElemVariable.execute(ElemVariable.java:248) 
    at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) 
    at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) 
    at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) 
    at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) 
    at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2400) 
    at org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(TransformerImpl.java:2270) 
    at org.apache.xalan.transformer.TransformerImpl.transformNode(TransformerImpl.java:1356) 
    at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:709) 
    at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1273) 
    at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1251) 
    at org.example.XalanExtension.transform(XalanExtension.java:67) 
    at org.example.XalanExtension.main(XalanExtension.java:81) 
Caused by: javax.xml.transform.TransformerException: Unknown error in XPath. 
    at org.apache.xpath.XPath.execute(XPath.java:365) 
    at org.apache.xpath.XPath.execute(XPath.java:303) 
    at org.apache.xpath.jaxp.XPathImpl.eval(XPathImpl.java:216) 
    at org.apache.xpath.jaxp.XPathImpl.evaluate(XPathImpl.java:281) 
    ... 25 more 
Caused by: java.lang.NullPointerException 
    at org.apache.xpath.axes.AxesWalker.setRoot(AxesWalker.java:221) 
    at org.apache.xpath.axes.ReverseAxesWalker.setRoot(ReverseAxesWalker.java:53) 
    at org.apache.xpath.axes.WalkingIterator.setRoot(WalkingIterator.java:157) 
    at org.apache.xpath.axes.NodeSequence.setRoot(NodeSequence.java:265) 
    at org.apache.xpath.axes.LocPathIterator.execute(LocPathIterator.java:212) 
    at org.apache.xpath.Expression.execute(Expression.java:155) 
    at org.apache.xpath.operations.Operation.execute(Operation.java:109) 
    at org.apache.xpath.XPath.execute(XPath.java:337) 
    ... 28 more 

SystemId Unknown; Line #14; Column #22; 
      Test: ../foo:a > 5 Result: 

は、どのように私は(それに提供文脈で)Xalanの拡張機能implmentation内のXPath式を評価しますか? XPathFactory/XPath instanceは正しく初期化されませんでしたか?

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:foo="org:example:foo" 
    xmlns:fun="xalan://org.example.XalanExtension" 
    version="1.0"> 

    <xsl:template match="*|@*"> 
     <xsl:apply-templates select="*|@*"/> 
    </xsl:template> 

    <xsl:template match="foo:test"> 
     <xsl:variable name="result" select="fun:evaluate(.)"/> 
     <xsl:message> 
      Test: <xsl:value-of select="."/> Result: <xsl:value-of select="$result"/> 
     </xsl:message> 
    </xsl:template> 

</xsl:stylesheet> 
<?xml version="1.0" encoding="utf-8"?> 
<tests xmlns="org:example:foo"> 
    <a>1</a> 
    <b>2</b> 
    <c>3</c> 
    <test>../foo:a &gt; 5</test> 
</tests> 

注:ここでは

は、上記のコードからの二つの文書があり、私はdyn:evaluate機能をよく知っています。この質問はそれとは関係ありません。

+0

ブール式 '../foo:a > 5'を評価しようとしていますが、ノードセット/ NodeListを返したいとしますか?それは拡張関数のコンテキスト外で動作しますか? –

+0

@MartinHonnen、そうです。オブジェクトを返すことになっています。そのミスキャストは問題ではなかったことに注意してください。 – predi

答えて

0

私は質問が早すぎました。いくつかのXalan拡張関数がどのように実装されているかを見て、XPath評価を実装するXalan固有のコードを見つけました(はい、dyn:evaluate)。

package org.example; 

import java.io.*; 
import java.util.logging.*; 
import javax.xml.transform.*; 
import javax.xml.transform.stream.*; 
import org.w3c.dom.*; 
import org.w3c.dom.traversal.NodeIterator; 
import org.apache.xalan.extensions.ExpressionContext; 
import org.apache.xpath.XPathContext; 
import org.apache.xpath.objects.XNodeSet; 

public class XalanExtension { 

    public static final String NS = "org:example:foo"; 

    public static final String XSLT = "" + 
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 
"<xsl:stylesheet \n" + 
" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n" + 
" xmlns:foo=\"org:example:foo\"\n" + 
" xmlns:fun=\"xalan://org.example.XalanExtension\"\n" + 
" version=\"1.0\"> \n" + 
" \n" + 
" <xsl:template match=\"*|@*\">\n" + 
"  <xsl:apply-templates select=\"*|@*\"/>\n" + 
" </xsl:template>\n" + 
" \n" + 
" <xsl:template match=\"foo:test\">\n" + 
"  <xsl:variable name=\"result\" select=\"fun:evaluate(.)\"/>\n" + 
"  <xsl:message>\n" + 
"   Test: <xsl:value-of select=\".\"/> Result: <xsl:value-of select=\"$result\"/>\n" + 
"  </xsl:message>\n" + 
" </xsl:template>\n" + 
" \n" + 
"</xsl:stylesheet>"; 

    public static final String XML = "" + 
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + 
"<tests xmlns=\"org:example:foo\">\n" + 
" <a>1</a>\n" + 
" <b>2</b>\n" + 
" <c>3</c>\n" + 
" <test>../foo:a &gt; 5</test>\n" + 
"</tests>"; 

    private TransformerFactory xalanTransFact; 

    public XalanExtension() { 
     xalanTransFact = new org.apache.xalan.processor.TransformerFactoryImpl(); 
    } 

    public void transform() { 
     try { 
      StringWriter writer; 

      writer = new StringWriter(); 

      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, "text"); 
      transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8"); 

      transformer.transform(
        new StreamSource(new StringReader(XML)), 
        new StreamResult(writer)); 

      System.out.println(writer.toString()); 
     } catch (TransformerConfigurationException ex) { 
      Logger.getLogger(XalanExtension.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (TransformerException ex) { 
      Logger.getLogger(XalanExtension.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 

    public static void main(String[] args) { 
     XalanExtension instance = new XalanExtension(); 
     instance.transform(); 
    } 

    public static final Object evaluate(ExpressionContext myContext, NodeIterator nodes) { 
     if (myContext instanceof XPathContext.XPathExpressionContext) { 
      XPathContext xctxt = null; 
      Node node = nodes.nextNode(); 
      if (node != null && node.hasChildNodes()) { 
       String xpathExpr = node.getFirstChild().getNodeValue(); 
       try { 
        xctxt = ((XPathContext.XPathExpressionContext) myContext).getXPathContext(); 
        org.apache.xpath.XPath dynamicXPath = new org.apache.xpath.XPath(xpathExpr, xctxt.getSAXLocator(), 
          xctxt.getNamespaceContext(), 
          org.apache.xpath.XPath.SELECT); 

        return dynamicXPath.execute(xctxt, myContext.getContextNode(), xctxt.getNamespaceContext()); 
       } catch (TransformerException e) { 
        return new XNodeSet(xctxt.getDTMManager()); 
       } 
      } 
     } 
     return null; 
    } 
} 

コードがorg.apache.xalanorg.apache.xpathパッケージからいくつかのクラスに依存しています。私の元の試みのように、標準のJAXPソリューションに頼ることで、おそらく同じことを達成することはできません。

関連する問題