2010-09-24 11 views
6

Próbowałem przekazać w3c.dom.Document, Element i NodeList jako parametry transformacji xslt.przekazywanie węzłów xml/dokumentów/fragmentów jako parametrów do xslt

Chcę być w stanie przetworzyć go w XSLT:

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

I przekazać parametr jako:

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

otrzymuję ten wyjątek:

„Nieprawidłowy konwersji z 'com.sun.org.apache.xerces.internal.dom.DocumentImpl' na 'node-set'. '

Próbowałem również exslt:node-set(), xalan:nodeset() itp., Ale to nie działa.

Wygląda na to, że wewnętrznie xalan oprócz własnej implementacji węzła.

Jak mogę zrobić coś podobnego bez ponoszenia tego problemu?

Nie mogę użyć document($param), ponieważ konstruuję dokument w locie.

Odpowiedz

3

(Delegowanie nową odpowiedź, jak poprzedni nie rozwiązuje problemu, a ten nowy jest radykalnie inny od poprzedniego)

Wydaje się być to znany problem z XALAN kompilacji procesor (XALANJ-2057, How can I pass a node as parameter to translets for XSLTC Processor).

Jakie są alternatywy?

  1. grzebania z URI jak przedstawiono w odpowiedzią How can I pass a node as parameter to translets for XSLTC Processor słupka
  2. Zamiast XALAN opracowującym procesora (XSLTC) zastosowanie XALAN interpretacyjnego procesor. Lub dowolny inny procesor XSLT, który obsługuje takie zachowanie.
  3. Zamiast tego użyj DTMAxisIterator , również przedstawionego w odpowiedzi na How can I pass a node as parameter to translets for XSLTC Processor post - nie jestem pewien, czy to zadziała.
  4. Tworzenie nowego drzewa DOM, łącząc swoje "parametru" Dom i oryginalny wejściowy XSLT dokumentu
+0

Dziękuję, zdecydowałem się na 4 – ithkuil

+1

Rozwiązanie 3 nie działa, gdy węzeł, który ma zostać przekazany jako parametr, pochodzi z dokumentu DOM, który nie jest przekształcanym dokumentem. – ithkuil

0

Jeśli spojrzeć na Document JavaDoc, można zobaczyć, że rozszerza interfejs Node, ale nie NodeList. Nie wiesz, czy to zadziała, ale możesz spróbować przekazać params.getChildNodes() zamiast params.

+0

niestety również próbował przekazać NodeList, ale bez powodzenia – ithkuil

+0

Może to jest związane z tym błędem? http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5059947 –

+0

W każdym razie proponuję pobrać stos tego błędu i wyśledzić w kodzie źródłowym Xalan określoną okoliczność, kiedy ten wyjątek zostanie zgłoszony. –

0

Oto przykład pracy z URIResolver Gambit, # 1 na liście rozwiązań:

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

    } 
} 

miałem też wersję roboczą, gdzie umieścić źródło xml w URI jak

xml://<urls><url><url id='google'>https://www.google.com</url>... 

, ale doszedłem do wniosku, że może gdzieś dojść do ograniczeń długości.

4

znalazłem rozwiązanie (tutaj: XSLT Processing with Java : passing xml content in parameter), który może działać w Twoim przypadku, a także:

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

zamiast tworzyć uriresolver z łańcucha, po prostu utworzyć źródło strumień z czytnikiem smyczkową i przekazać go do arkusza stylów.

Potem byłem w stanie uzyskać dostęp do dokumentu zwykle jako XML:

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

nie testowałem z Xalan, ale może odpowiedź będzie pomagać innym, którzy potykają na to pytanie :)