2017-01-31 1 views
0

Xalan 2.7.1에 의해 확장 기능에 제공된 컨텍스트 내에서 XPath 식을 평가하려고합니다. 어떤 이유로 Xalan에서 내부 예외가 발생하면 항상 실패합니다.Xalan 확장 함수 구현 내에서 XPath 식을 어떻게 평가합니까?

참고 :이 작업을 실행하려면 classpath에 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'을 평가하려고하지만 node-set/NodeList를 반환하겠습니까? 확장 기능 컨텍스트 외부에서 작동합니까? –

+0

@MartinHonnen, 예. 그것은 어떤 객체라도 돌려 주어야한다. 그 miss-cast는 문제가 아니 었습니다. – 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 솔루션을 사용하여 동일한 결과를 얻지 못할 수도 있습니다.

관련 문제