2010-09-24 109 views
6

我嘗試將w3c.dom.Document,ElementNodeList作爲參數傳遞給xslt變換。將xml節點/文檔/片段作爲參數傳遞給xslt

我希望能夠在XSLT內對其進行處理:

<xsl:param name="links" /> 
<xsl:template match="/"> 
    <record> 
     <xsl:for-each select="$links/*"> 
      <test /> 
     </xsl:for-each> 
    </record> 
</xsl:template> 

我傳遞參數爲:

 Document params = createLinksParams(links); 
     transformer.setParameter("links", params); 

我得到這個異常:

「轉換無效從'com.sun.org.apache.xerces.internal.dom.DocumentImpl'到'node-set'。'

我也試過exslt:node-set()xalan:nodeset()等,但它不起作用。

看來,內部xalan除了他自己的Node實現。

如何在不引發此問題的情況下做類似的事情?我不能使用document($param),因爲我正在構建文檔。

回答

3

(發佈一個新的答案,因爲前一個沒有解決的問題,而這個新的不同於以往完全不同)

似乎是一個已知的問題與XALAN編譯處理器(XALANJ-2057How can I pass a node as parameter to translets for XSLTC Processor)。

那麼,有什麼替代方案?

  1. 用的URI如 概述的響應於How can I pass a node as parameter to translets for XSLTC Processor
  2. 代替 XALAN編譯處理器(XSLTC) 使用XALAN解釋性處理器更動。或者支持這種行爲的任何其他XSLT處理器。
  3. 使用DTMAxisIterator 取而代之,也在對How can I pass a node as parameter to translets for XSLTC Processor帖子的回覆中列出 - 不知道它是否會起作用。
  4. 創建一個新的DOM樹,結合你的「參數」 DOM和原始XSLT輸入文檔
+0

謝謝你,我選擇了4 – ithkuil 2010-09-26 08:39:25

+1

當要作爲參數傳遞的節點來自不是要轉換的文檔的DOM文檔時,解決方案3似乎不工作。 – ithkuil 2010-09-26 10:51:22

0

如果你看看Document JavaDoc,你可以看到它擴展了Node接口,但不是NodeList。不知道它是否會工作,但你可以嘗試通過params.getChildNodes()而不是params

+0

不幸的是我也嘗試通過NodeList,但沒有運氣 – ithkuil 2010-09-24 17:38:10

+0

也許它是與這個bug有關? http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5059947 – 2010-09-24 17:48:26

+0

無論如何,我會建議採取該錯誤的堆棧跟蹤,並追溯在Xalan源代碼中拋出此異常的具體情況。 – 2010-09-24 17:50:10

0

下面是用的URIResolver開局,在解決方案列表#1的工作示例:

import javax.xml.transform.Source; 
import javax.xml.transform.Transformer; 
import javax.xml.transform.TransformerException; 
import javax.xml.transform.TransformerFactory; 
import javax.xml.transform.URIResolver; 
import javax.xml.transform.stream.StreamResult; 
import javax.xml.transform.stream.StreamSource; 
import java.io.StringReader; 
import java.io.StringWriter; 

public class XSLTest { 
    public static void main(String[] args) { 

     class MyResolver implements URIResolver { 
      String _xml; 
      MyResolver(String xml) { _xml = xml; } 
      @Override 
      public Source resolve(String href, String base) throws TransformerException { 
       return new StreamSource(new StringReader(_xml)); 
      } 
     } 

     String lookup = 
      "<?xml version='1.0' encoding='utf-8'?>\n" + 
      "<urls>\n" + 
      " <url id='google'>https://www.google.com</url>\n" + 
      " <url id='yahoo'>https://www.yahoo.com</url>\n" + 
      " <url id='apple'>https://www.apple.com</url>\n" + 
      "</urls>"; 

     String main = 
      "<?xml version='1.0' encoding='utf-8'?>" + 
      "<list>"+ 
      " <link ref='yahoo'>Yahoo</link>"+ 
      " <link ref='google'>Google</link>"+ 
      "</list>"; 

     String xsl = 
      "<?xml version='1.0' encoding='UTF-8'?>\n" + 
      "<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>\n" + 
      " <xsl:param name='lookup-doc' />\n" + 
      " <xsl:variable name='lookup' select='document($lookup-doc)'/>\n" + 
      " <xsl:template match='/'>\n" + 
      "  <xsl:for-each select='//link'>\n" + 
      "   <xsl:variable name='ref' select='@ref'/>\n" + 
      "   <xsl:element name='a'>\n" + 
      "    <xsl:attribute name='href'>\n" + 
      "     <xsl:value-of select='$lookup//url[@id=$ref]'/>\n" + 
      "    </xsl:attribute>\n" + 
      "    <xsl:value-of select='text()'/>\n" + 
      "   </xsl:element>\n" + 
      "  </xsl:for-each>\n" + 
      " </xsl:template>\n" + 
      "</xsl:stylesheet>"; 

     try { 

      // xsl doc 
      Source xsltSource = new StreamSource(new StringReader(xsl)); 

      TransformerFactory transFact = TransformerFactory.newInstance(); 
      Transformer trans = transFact.newTransformer(xsltSource); 

      // main doc 
      Source mainSource = new StreamSource(new StringReader(main)); 

      // lookup doc - stage it in the URI resolver 
      trans.setURIResolver(new MyResolver(lookup)); 
      // dummy URL, you could use different values here to 
      // support multiple document parameters 
      trans.setParameter("lookup-doc", "xml://lookup"); 

      StringWriter out = new StringWriter(); 
      trans.transform(mainSource, new StreamResult(out)); 

      System.out.println(out.toString()); 

     } catch (TransformerException e) { 
      System.err.println("It's the wrong trousers Gromit, and they've gone wrong!"); 
      e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. 
     } 

    } 
} 

我也有,我把XML源的URI像

xml://<urls><url><url id='google'>https://www.google.com</url>... 
工作版本

但我想這可能會遇到長度限制的地方。

4

我找到了解決方法(在這裏:XSLT Processing with Java : passing xml content in parameter),這可能是你的情況下工作,以及:

String urls = "<urls><url id='google'>https://www.google.com</url>..."; 
trans.setParameter("lookupdoc", new StreamSource(new StringReader(urls))); 

,而不是從一個字符串創建的URIResolver,只需創建一個字符串reader流源,並將其傳遞到樣式表。

在那之後,我能正常訪​​問文檔的XML:

<xsl:param name="lookupdoc"><urls/></xsl:param> 
... 
<xsl:variable name="googleurl" select="$lookupdoc/@id='google"/> 

沒有與xalan的測試,但也許答案將幫助其他人誰碰上了這個問題:)