2017-01-23 2 views
1

Я в тупике о том, почему следующая примерная программа отказывается правильно применять мою таблицу стилей. Кажется, что dyn:evaluate в Xalan 2.7.1 отказывается обрабатывать определенные переменные XPath.Является ли dyn: оцените функцию расширения, известную как проблема в Xalan-J 2.7.1?

Запуск следующей программы с 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), который принимает входной файл (INPUT, input.xml), открытый через функцию document(), как «аргумент». Этот входной файл содержит набор элементов, которые протестированы с помощью выражений XPath (в примере).

Выход из программы указывает, что функция dyn:evaluate поддерживается, что input.xml правильно прочитано, что простые выражения XPath оцениваются правильно, но как только переменная XPath задействована, она ломается.

Считываемые версии всех документов, представленных ниже.

Input.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> 

Пример

<?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 аргумент? Я правильно определяю выражения? Пытаясь запустить эту таблицу стилей в oXygen с выбранным Xalan, сообщает java.lang.RuntimeException: ElemTemplateElement error: Function not supported!, когда впервые встречается переменная XPath.

Edit:

Я переписал вопрос, чтобы выяснить, что моя фактическая проблема.

+0

Ваш вопрос сбивает с толку. Вы можете проверить, поддерживает ли ваш процессор функцию с помощью функции 'function-available()'. Если функция поддерживается, и вы получаете результаты, которые отличаются от ожидаемых, отправьте воспроизводимый пример. –

+0

@michael, это воспроизводимый пример. Просто запустите код с помощью xalan-j в classpath. Функция оценки поддерживается, и функция-функция возвращает True для нее. Однако он не оценивает выражения должным образом. Пожалуйста, дайте мне знать, как я могу очистить вашу путаницу. – predi

+0

Что произойдет, если вы используете 'org.apache.xalan.xsltc.trax.TransformerFactoryImpl' вместо' org.apache.xalan.processor.TransformerFactoryImpl'? Xalan имеет две реализации XSLT 1.0, поэтому, возможно, oXygen использует процессор xsltc. –

ответ

0

Как опасались, фрагменты дерева результатов в переменных XPath, по-видимому, не поддерживаются dyn:evaluate в Xalan 2.7.1. Обратите внимание, что переменные с значениями фрагмента дерева результата не работают.

Я написал свою собственную функцию расширения (dyn:evaluate эквивалент), которая оценивает выражения XPath, но также не удалось обработать фрагмент результирующего дерева в переменной (получено this method is not yet supported исключений). Это может быть ограничением реализации механизма XPath, предоставляемого JAXP.

Возможно, он будет работать с другой версией механизма XPath.

Я отказался от попыток выполнить эту работу и не буду заполнять фрагменты дерева результатов в переменных XPath, когда dyn:evaluate находится в игре. Я просто предоставил информацию, необходимую для оценки моих условий, используя строковое значение xsl:param вместо того, чтобы использовать жесткий XML-файл. Функция расширения для Xalan будет проверять, присутствует ли выбор, или нет.

Смежные вопросы