aragorna: pdf fop und Sonderzeichen

Hallo,

habe das gleiche Problem wie Bingoman Babenco aus Thread http://forum.de.selfhtml.org/archiv/2007/5/t152792/
und wäre über weitere Informationen echt dankbar.

Sonderzeichen können bei mir auch nicht dargestellt werden.

Nachdem ich versucht hatte den font ArialUnicodeMS einzubinden, kam zunächst immer die Fehlermeldung:
unknown font ArialUnicodeMS,normal,normal so defaulted font to any

Dann habe ich es mit
File userConfigFile = new File("D:/xxx/fopConf/userconfig.xml");
Options options = new Options(userConfigFile);

in meinem java code versucht, damit der neue font bekannt wird. Aber wenn ich das PDF generieren will, bekomme ich immer einen OutOfMemory error.

Der link
http://xmlgraphics.apache.org/fop/0.93/running.html#memory
hat auch nicht weitergeholfen.

Hinzu kommt, daß ich mich nicht so gut mit fop auskenne, daß ich das Stylesheet mal schnell überarbeiten und "verschlanken" könnte.

Hat jemand von euch noch eine Idee?

Vielen Dank für die Hinweise,

aragorna

  1. Hallo,

    Könntest du mal etwas mehr Code zeigen? So wird das zum Rätselraten. Out of Memory hat nicht unbedingt etwas mit Sonderzeichen zu tun. Meistens liegt es an einem nicht gerade optimalen Stylesheet. Zudem könntest du auch mal versuchen, deinen output zu "kontrollieren". Dir Ergebnisse in möglichen Zwischenschritten anschauen und verfolgen, ob irgendwo ziem,lich viel Daten "erstellt" werden - aber so ganz ohne Code bleibt es halt nur Rätselraten.

    Gruß, H.

    1. Hallo,

      Könntest du mal etwas mehr Code zeigen? So wird das zum Rätselraten. Out of Memory hat nicht unbedingt etwas mit Sonderzeichen zu tun. Meistens liegt es an einem nicht gerade optimalen Stylesheet. Zudem könntest du auch mal versuchen, deinen output zu "kontrollieren". Dir Ergebnisse in möglichen Zwischenschritten anschauen und verfolgen, ob irgendwo ziem,lich viel Daten "erstellt" werden - aber so ganz ohne Code bleibt es halt nur Rätselraten.

      Gruß, H.

      Hallo Holger,

      vielen Dank für deine Antwort. Was meinst du mit "kontrollieren"?

      Du meinst sicher den Code vom Stylesheet, oder? Das sieht so aus (ist eine Testdatei):

      <?xml version="1.0" encoding="iso-8859-1"?> <xsl:stylesheet version="1.0"    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"    xmlns:fo="http://www.w3.org/1999/XSL/Format">

      <xsl:param name="order_language_file_content"/> <xsl:param name="order_language_file_content"/> <xsl:param name="systemdatum"/> <xsl:param name="order_language"/> <xsl:param name="user_country"/> <xsl:param name="isoCode"/>

      <xsl:template match='/'>   <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">    fo:layout-master-set     <fo:simple-page-master         page-height="29.7cm" page-width="21cm"         margin-top="2cm"     margin-bottom="2cm"         margin-left="1.5cm"  margin-right="0.5cm"         master-name="first">

      <fo:region-body margin-top="1cm" margin-bottom="1.5cm"/>       <fo:region-before extent="1cm"/>       <fo:region-after extent="1.5cm"/>     </fo:simple-page-master>    </fo:layout-master-set>

      <xsl:for-each select='/saison/spieltag[@spnr>=15]' >     <xsl:variable name='sp_nr' select='@spnr' />     <fo:page-sequence master-reference="first">       <fo:static-content flow-name="xsl-region-before">         <fo:block line-height="14pt" font-size="14pt"     text-align="start">Spieltag:     <xsl:value-of select='$sp_nr' />  </fo:block>       </fo:static-content>       <fo:static-content flow-name="xsl-region-after">       <fo:block line-height="14pt" font-size="10pt"   text-align="end">Page fo:page-number/</fo:block>     </fo:static-content>

      <fo:flow flow-name="xsl-region-body" font-family='arialuni' font-size='12pt'>

      <fo:block space-before.optimum="3pt" space-after.optimum="3pt">       Paarungen       </fo:block>

      <fo:table border-style="solid" border-width="0pt"                                      border-color="red"          table-layout="fixed">  <fo:table-column column-width="0.75cm"/>  <fo:table-column column-width="4cm"/>  <fo:table-column column-width="0.2cm"/>  <fo:table-column column-width="4cm"/>  <fo:table-column column-width="0.5cm"/>

      fo:table-body

      <xsl:apply-templates select='/saison/spieltag[@spnr=$sp_nr]/paar' />

      </fo:table-body>      </fo:table >

      <fo:block space-before.optimum="18pt"                 space-after.optimum="3pt">         Tips       </fo:block>

      <!-- fo:table-and-caption

      fo:table-caption     fo:block        Tips     </fo:block>  </fo:table-caption>       -->

      <fo:table border-style="solid" border-width="0pt"                                            border-color="blue"                              table-layout="fixed">  <fo:table-column column-width="3cm"/>

      <fo:table-column column-width="1cm"/>  <fo:table-column column-width="1cm"/>  <fo:table-column column-width="1cm"/>

      <fo:table-column column-width="1cm"/>  <fo:table-column column-width="1cm"/>  <fo:table-column column-width="1cm"/>

      <fo:table-column column-width="1cm"/>  <fo:table-column column-width="1cm"/>  <fo:table-column column-width="1cm"/>

      fo:table-body         fo:table-row

      fo:table-cell              fo:block <xsl:value-of select="$order_language_file_content/TranslationOrderPrint/Header/ListOfItem/Item/Row[30]"/> Test polnische Zeichen</fo:block>           </fo:table-cell>

      <xsl:for-each select="/saison/spieltag[@spnr=$sp_nr]/paar">              fo:table-cell                <fo:block background-color='yellow' text-align='center' start-indent='2mm' end-indent='2mm'>                   <xsl:value-of select="@pid" />                </fo:block>              </fo:table-cell>           </xsl:for-each>         </fo:table-row>

      <!-- xsl:apply-templates select='/saison/spieltag[@spnr=$sp_nr]/paar[@pid=0]/tips' / -->         <xsl:apply-templates select='/saison/spieltag[@spnr=$sp_nr]' mode='tips' />

      </fo:table-body>       </fo:table>      <!--      </fo:table-and-caption >      -->

      </fo:flow>

      </fo:page-sequence> </xsl:for-each>  </fo:root> </xsl:template>

      <xsl:template match='spieltag'>    <!-- xsl:value-of select='@spnr' / -->

      <xsl:apply-templates select='paar' />

      <!-- fo:table-row>      fo:table-cell        fo:block - </fo:block>      </fo:table-cell>    </fo:table-row -->

      </xsl:template>

      <xsl:template match='paar'>

      <fo:table-row space-before.optimum='2mm'>    fo:table-cell      <fo:block background-color='yellow' text-align='center' start-indent='2mm' end-indent='2mm'>         <xsl:value-of select="@pid" />      </fo:block>    </fo:table-cell>

      <xsl:variable name="hid" select="heim" />    <xsl:variable name="gid" select="gast" />

      fo:table-cell     fo:block        <xsl:value-of select="//vereine/v[@vid=$hid]/vname" />     </fo:block>    </fo:table-cell>

      fo:table-cell     fo:block : </fo:block>    </fo:table-cell>

      fo:table-cell     fo:block        <xsl:value-of select="//vereine/v[@vid=$gid]/vname" />     </fo:block>    </fo:table-cell>

      fo:table-cell     <fo:block font-weight='650'               font-family='arialuni'        start-indent='2mm'>        <xsl:value-of select="result" />     </fo:block>    </fo:table-cell>

      </fo:table-row> </xsl:template>

      <xsl:template match='spieltag' mode="tips">

      <fo:table-row space-before.optimum='5mm'                 space-after.optimum='5mm'>      fo:table-cell            fo:blockr e s u l t</fo:block>      </fo:table-cell>

      <xsl:for-each select='paar'>       <xsl:apply-templates select="result" />     </xsl:for-each>   </fo:table-row>

      <xsl:for-each select='paar[@pid=0]'>

      <xsl:for-each select='tips/tip'>

      <fo:table-row space-before.optimum='5mm'>

      <xsl:variable name='t_id'  select='@tid' />

      fo:table-cell            fo:block              <xsl:value-of select="//tipper/t[@tid=$t_id]/tname" />            </fo:block>          </fo:table-cell>

      <xsl:apply-templates select="../../../paar[@pid=0]/tips/tip[@tid=$t_id]" />      <xsl:apply-templates select="../../../paar[@pid=1]/tips/tip[@tid=$t_id]" />      <xsl:apply-templates select="../../../paar[@pid=2]/tips/tip[@tid=$t_id]" />      <xsl:apply-templates select="../../../paar[@pid=3]/tips/tip[@tid=$t_id]" />      <xsl:apply-templates select="../../../paar[@pid=4]/tips/tip[@tid=$t_id]" />      <xsl:apply-templates select="../../../paar[@pid=5]/tips/tip[@tid=$t_id]" />      <xsl:apply-templates select="../../../paar[@pid=6]/tips/tip[@tid=$t_id]" />      <xsl:apply-templates select="../../../paar[@pid=7]/tips/tip[@tid=$t_id]" />      <xsl:apply-templates select="../../../paar[@pid=8]/tips/tip[@tid=$t_id]" />      </fo:table-row>

      </xsl:for-each>

      </xsl:for-each>

      </xsl:template>

      <xsl:template match='result'>

      fo:table-cell      <fo:block text-align='center'                font-family='arialuni' font-size='13' font-weight='normal'>        <xsl:value-of select="." />      </fo:block>    </fo:table-cell> </xsl:template>

      <xsl:template match='result___' mode="pur">

      <xsl:value-of select="." />

      <!-- xsl:apply-templates select="htore" / -->   <!-- xsl:apply-templates select="gtore" / -->

      </xsl:template>

      <xsl:template match='tips'>   <xsl:for-each select="tip[@tid='0']">     <xsl:variable name="id" select='@tid' />

      fo:table-row

      fo:table-cell        fo:block         <xsl:value-of select="//tipper/t[@tid=$id]/tname" />        </fo:block>       </fo:table-cell>

      <xsl:apply-templates select="../tip[@tid='0']" />       <xsl:apply-templates select="../tip[@tid='1']" />       <xsl:apply-templates select="../tip[@tid='2']" />       <xsl:apply-templates select="../tip[@tid='3']" />

      </fo:table-row>

      </xsl:for-each> </xsl:template>

      <xsl:template match='tip'>

      fo:table-cell     xsl:choose       <xsl:when test="res=1">         <fo:block text-align='center'                   background-color="blue"     color='yellow'     font-family="arialuni"     start-indent="2mm"     end-indent="2mm"     font-weight="650">           <!--             <xsl:value-of select="../../@pid" />,             <xsl:value-of select="@tid" />,           -->           <xsl:value-of select="vor" />        </fo:block>       </xsl:when>       xsl:otherwise         <fo:block text-align="center"                   font-family="arialuni"     font-weight="150">           <!--             <xsl:value-of select="../../@pid" /> ,             <xsl:value-of select="@tid" />,           -->           <xsl:value-of select="vor" />        </fo:block>       </xsl:otherwise>     </xsl:choose>   </fo:table-cell> </xsl:template>

      </xsl:stylesheet>

      Vielen Dank für weitere Anregungen.

      Grüße,

      aragorna

      1. Hallo nochmal,

        hier der java code dazu: Es soll ein pdf generiert werden, das auf Platte gespeichert wird, diese soll danach direkt im Browser angezeigt werden. Anscheinend wird die outofmemory exception nach dem Generieren geworfen, denn die Datei ist vorhanden. Aber wenn ich sie dann explizit durch Doppelklick öffnen möchte, dann wird gesagt, die Datei sei kaputt und könnte nicht repariert werden.

        File file = new File("D:/xxx/fopConf/userconfig.xml"); //userconfig.xml
        Options options = new Options(file);

        File pdf = new File(outDir, pdfName+docNo+".pdf");  //output Path for PDF Document

        //Construct driver
        Driver driver = new Driver();

        //Setup logger
        org.apache.avalon.framework.logger.Logger log = new ConsoleLogger(ConsoleLogger.LEVEL_INFO);
        driver.setLogger(log);
        MessageHandler.setScreenLogger(log);

        //Setup Renderer (output format)
        driver.setRenderer(Driver.RENDER_PDF);

        // Setup output
        OutputStream out = new java.io.FileOutputStream(pdf);
        try {
            driver.setOutputStream(out);

        //Setup XSLT
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory.newTransformer(new StreamSource(isXsl));

        //Resulting SAX events (the generated FO) must be piped through to FOP
            Result res = new SAXResult(driver.getContentHandler());

        System.out.println(" driver.getContentHandler =  " + driver.getContentHandler());

        //Set Parameters to XSL
            Enumeration enum = para.keys();
           while (enum.hasMoreElements())
           { String key = (String) enum.nextElement();
           System.out.println("key ==  " + key);
           System.out.println("para.get(key) == " + para.get(key));
             transformer.setParameter(key,para.get(key));
           }
            //Start XSLT transformation and FOP processing
            transformer.transform(new DOMSource(doc), res);

        driver=null;
            transformer=null;
            factory=null;

        } catch (Exception e) {
          e.printStackTrace();
         } finally {

        out.close();
        }

        Vielen Dank für die Hilfe,

        aragorna

        1. Hallo,

          hier der java code dazu: Es soll ein pdf generiert werden, das auf Platte gespeichert wird, diese soll danach direkt im Browser angezeigt werden. Anscheinend wird die outofmemory exception nach dem Generieren geworfen, denn die Datei ist vorhanden. Aber wenn ich sie dann explizit durch Doppelklick öffnen möchte, dann wird gesagt, die Datei sei kaputt und könnte nicht repariert werden.

          Wie groß ist denn die erstellte Datei?
          Dass der PDF-Reader meckert, deutet darauf hin, dass während der Transformation etwas schiefgegangen ist. Ich habe dein XSLT jetzt nicht überprüft.

          Es muss jedenfalls irgendwo ein Logfile geben in dem die Fehlermeldungen vom FOP geschreiben werden (oder du muss halt in der Konsole schauen was FOP während der Transformation da hineinschreibt)

          Hier der Code, den ich verwende, jetzt schnell auf das Wesentliche gekürzt, (also kann sein, dass ich wo zu viel gelöscht habe).
          (den ClassLoader brauche ich, weil ich die config.xml und die XSL(s) aus einem/dem Jar-File lade)

          public class XML2PDF {
              public static void createPDF(String[] args) {
                  try {
                      ClassLoader cl = XML2PDF.class.getClassLoader();
                      DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
                      Configuration cfg = cfgBuilder.build(cl.getResourceAsStream(args[0]));

          File xmlfile = new File(args[1]);
                      File xsltfile = new File(args[2]);
                      File pdffile = new File(args[3]);

          FopFactory fopFactory = FopFactory.newInstance();
                      fopFactory.setUserConfig(cfg);

          FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

          OutputStream out = new java.io.FileOutputStream(pdffile);
                      out = new java.io.BufferedOutputStream(out);

          try {
                          Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);

          TransformerFactory factory = TransformerFactory.newInstance();
                          Transformer transformer = factory.newTransformer(new StreamSource(cl.getResourceAsStream(args[2])));

          src = new StreamSource(xmlfile);
                          Result res = new SAXResult(fop.getDefaultHandler());

          transformer.transform(src, res);
                      } finally {
                          out.close();
                      }
                  } catch (Exception e) {
                      e.printStackTrace(System.err);
                  }
              }
          }

          Grüße
          Thomas

      2. Hallo,

        hm, schwer zu sagen wo es klemmt da keine beispiel xml gegeben ist. Allerdings ein, zwei sachen zu deinem stylesheet.

        <xsl:param name="order_language_file_content"/>
        <xsl:param name="order_language_file_content"/>

        Doppelte parameter mag so ziemlich kein parser ;-)

        <xsl:for-each select='/saison/spieltag[@spnr>=15]' >
         ...
          <xsl:apply-templates select="/saison/spieltag[@spnr=$sp_nr]/paar"/>
             ...
              <xsl:for-each select="/saison/spieltag[@spnr=$sp_nr]/paar">
              ...
              </xsl:for-each>
             ...
                 <xsl:apply-templates select="/saison/spieltag[@spnr=$sp_nr]" mode="tips"/>
          ...
        </xsl:for-each>

        Bist du dir sicher das dies so gewollt ist? Die Xpath Anweisung ist überflüssig und es könnte auch ganz einfach  <xsl:apply-templates select="paar"/> stehen.

        Mit "kontrollieren" meine ich, ob du dir mal die xml datei angeschaut hast, die aus dem stylesheet erzeugt wird? einfach mal saxon laufen lassen und das ergebnis mal im editor betrachten.

  2. Hallo,

    habe das gleiche Problem wie Bingoman Babenco aus Thread http://forum.de.selfhtml.org/archiv/2007/5/t152792/
    und wäre über weitere Informationen echt dankbar.

    Sonderzeichen können bei mir auch nicht dargestellt werden.

    Nachdem ich versucht hatte den font ArialUnicodeMS einzubinden, kam zunächst immer die Fehlermeldung:
    unknown font ArialUnicodeMS,normal,normal so defaulted font to any

    Hast du die Schritte für das Einbetten der Fonts (im erwähnten Thread ist es beschrieben) gemacht und hast du dann im (user)config.xml das richtig angegeben?

    Dann habe ich es mit
    File userConfigFile = new File("D:/xxx/fopConf/userconfig.xml");
    Options options = new Options(userConfigFile);

    Das würde ich eher so machen:

    File userConfigFile = new File("D:/xxx/fopConf/userconfig.xml");
    DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
                Configuration cfg = cfgBuilder.build(userConfigFile);

    FopFactory fopFactory = FopFactory.newInstance();
    fopFactory.setUserConfig(cfg);

    Grüße
    Thomas

    1. Hallo Thomas,

      vielen Dank für deine Antwort.

      Hast du die Schritte für das Einbetten der Fonts (im erwähnten Thread ist es beschrieben) gemacht und hast du dann im (user)config.xml das richtig angegeben?

      Ich denke schon, die Fehlermeldung kommt jetzt auch nicht mehr.

      Das würde ich eher so machen:

      File userConfigFile = new File("D:/xxx/fopConf/userconfig.xml");
      DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
                  Configuration cfg = cfgBuilder.build(userConfigFile);

      Wobei aber die cfg kein File nimmt, da muss man wohl noch einen InputStream draus machen.

      FopFactory fopFactory = FopFactory.newInstance();
      fopFactory.setUserConfig(cfg);

      Ich werde das mal probieren.

      Vielen Dank,

      aragorna

    2. Ach ja, ist vielleicht noch wichtig zu wissen, daß ich noch fop0.20.5 benutze.

      aragorna