23.09.2010

Стварэнне PDF з кода з FOP

Original on grover.open2space.com

У мяне нядаўна быў праект, які неабходна зрабіць шматлікае з ліку храбусценне, а затым стварыць PDF прадставіць гэтыя лічбы і графік, а таксама. Гэта прадстаўлена дзве праблемы для мяне – як стварыць PDF з кода, і, як стварыць дыяграму для выкарыстання ў рамках гэтага PDF. Я магу сказаць, што дамагліся вызначаных поспехаў і жадаю падзяліцца з вамі працэсу. Я буду казаць пра бок PDF рэчаў у гэтым артыкуле, і пасля іншага хутка з падрабязнай інфармацыяй пра тое, як я звяртаўся з графіка. Але агляд графік рашэння прыведзена ніжэй.

Па-першае, яшчэ некалькі фону. У рамках праекта таксама неабходна асобнае вэб-інтэрфейс для пошуку храбусцеў дадзеных з дыяпазоны дат, ці пэўных месцах. Мы з самага пачатку вырашылі, што мы будзем выкарыстоўваць PHP для гэтага, як было б досыць хутка, каб зрабіць гэта, а таксама ажыццяўленне інфраструктуры, якія могуць расці. Адной галоўнай болевай кропкай тут з’яўляецца тое, што нам трэба PHP на сервер LAMP пагаварыць з прысвечаны Windows MSSQL 2005 сервер, які працуе на Windows 2003 акно. Пасля кучу капаць апыняецца, што PHP на серверы Ubuntu запатрабаванняў php5-Sybase пакет усталяваны, а затым з дапамогай MSSQL функцыі працуюць звычайна. Я знайшоў старонку, якая дала мне вялікі ўзор кода неабходна пачынаць з.

Бачачы, як мы выкарыстоўвалі PHP для пошуку частка праекта, мы вырашылі выкарыстоўваць яго, каб дапамагчы стварыць PDF, а таксама. Зараз, PHP можа генераваць PDF-файламі напроста, але працэс даволі аднастайны. Бібліятэкі паказваюць, што неабходна стварыць і становішча ўсё ўручную, а таксама клопат пра парывы старонак уручную. Замест гэтага, мясцовыя Linux Users Group прыйшла праз (ізноў жа) і прапанаваў альтэрнатыву. Ніл Мэйхью, з праграмаваннем Special Interest Group (PROGSIG), прапанаваў прапанова для нас FOP. FOP з’яўляецца праект Apache, што робіць PDF пакаленні вельмі проста. Гэта прыкладанне Java, так што вам неабходна асяроддзі Java, але гэта можна назваць заяву каманднага радка. Адзінай рэальнай праблемай тут з’яўляецца тое, што FOP выкарыстоўвае XML і XSL-FO. Мы былі ўжо мае намер па ўводзе дадзеных у XML для лёгкага перакладу з дапамогай XSLT. Такім чынам, мы толькі трэба пайсці далей і стварыць XSL-FO заявы (якая пашырэннем XSLT).

Другая перашкода была дыяграмы. Мы першапачаткова вырашылі выкарыстоўваць Google Charts таму што гэта было хутка і лёгка. Тым не менш, мы хутка пабеглі ў абмежаванні агульнага і вольнага трэці ўдзельнік рашэнне. Вядома, некаторыя пытанні могуць быць вырашаны, але, улічваючы аб’ём дадзеных мы будзем маляваць графікі, і межы URL памер, мы будзем мець праблемы. Акрамя таго было этычнага / адказнае пытанне пра перадачу нашых унутраных дадзеных праз трэція серверы партыі толькі для простых графаў. Такім чынам, мы зноў паглядзеў у альтэрнатыў. Рашэнне апынулася SVG. Выкарыстанне XSL-FO мы маглі б стварыць і embedd SVG-кода. SVG сам XML-фармат, так што гэта было лёгка. Мы загарэўся Inkscape і стварыў фіктыўны графік лініі для выкарыстання ў якасці базы для нашых дынамічных дыяграм.

З планам на месцы, каб пакрыць нявырашаных пытаннях, мы пачалі кадаванні. Акрамя таго (дробных) навучанні для XSL-FO і SVG, мы былі ўражаны тым, як хутка ўсё зваліліся разам. Мы правялі больш часу працы, як атрымаць нашы дадзеныя з базы дадзеных, чым мы зрабілі будынак дакладу.

Для тых, хто жадае ўбачыць гэта ў дзеянні, вось просты How-To.

1. Стварыце свой XML.

Па гэтай інструкцыі мы будзем выкарыстоўваць наступныя:

  <?xml version="1.0" encoding="ISO-8859-1"?>
  <mydata>
    <record>
      <date>1 May 2008</date>
      <earnings>100.00</earnings>
    </record>
    <record>
      <date>1 May 2008</date>
      <earnings>150.00</earnings>
    </record>
    <record>
      <date>1 May 2008</date>
      <earnings>80.00</earnings>
    </record>
    <record>
      <date>1 May 2008</date>
      <earnings>200.00</earnings>
    </record>
  </mydata>

Вы будзе будаваць гэта з уласнымі дадзенымі і структуры, вядома. PHP DOM аб’ект карысным тут.

Адна рада. Гэта значна прасцей, каб ваш код рабіць любую колькасць неабходных храбусценне, чым ён жадае мець XSLT гэта зрабіць. І значна лягчэй зразумець, занадта. Калі вам трэба агульнае любых слупкоў, ці вызначыць, штосьці дынамічна, што ўплывае на фарматаванне – ваш код гэта зрабіць, і элементы ўставіць XML для ўяўлення гэтых дадзеных. Трымаеце XSLT рэчы простымі справамі макета. Я ўпэўнены, XML / XSLT фанатыкаў там скажа мне гэта не трэба. Але я лічу, што я больш прадуктыўнай, калі я раблю складаныя рэчы ў кодзе ў першую чаргу.

2. Стварыце свой XSL-FO дакумент.

Калі вы калі-небудзь рабіў XSLT файл, тое гэта адносна лёгка. У адваротным выпадку, ён можа быць вельмі загадкавыя і ўзяць трохі абвыкнуць. Добрай крыніцай для пачатку можна знайсці на W3Schools. Урэшце вы будзеце мець дакумент вось накшталт гэтага:

<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet version="1.0"
        xmlns:fo="http://www.w3.org/1999/XSL/Format"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" version="1.0" indent="yes" encoding="UTF-8"/>

  <xsl:template match="mydata">
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">

      <fo:layout-master-set>
        <fo:simple-page-master  master-name="summarypage"
                              page-height="11in"
                              page-width="8.5in"
                              margin-top="1in"
                              margin-bottom="1in"
                              margin-left="1in"
                              margin-right="1in"
                              >
          <fo:region-body />
        </fo:simple-page-master>
      </fo:layout-master-set>

      <fo:page-sequence master-reference="summarypage">
        <fo:flow flow-name="xsl-region-body">

          <!-- Report Header -->
          <fo:block text-align="center"
                    font-size="18pt"
                    font-weight="bold">My Custom PDF Report</fo:block>

          <fo:block text-align="center"
                    font-size="14pt"
                    font-weight="bold"
                    padding-after="0.25in">Showing Some data</fo:block>

          <!-- Current Numbers -->
          <fo:block text-align="center"
                    font-size="8pt">

            <fo:table table-layout="fixed" width="100%">
              <fo:table-body>
                <fo:table-row background-color="#000"
                              border-left-style="solid"
                              border-right-style="solid"
                              border-top-style="solid">
                  <fo:table-cell >
                   <fo:block color="#fff"
                                text-align="center"
                                padding-top="0.5em"
                                padding-bottom="0.5em">
                                  Date
                   </fo:block>
                   </fo:table-cell>
                  <fo:table-cell >
                    <fo:block color="#fff"
                                 text-align="center"
                                 padding-top="0.5em"
                                 padding-bottom="0.5em">
                                   Earnings
                    </fo:block>
                  </fo:table-cell>
                </fo:table-row>
                <xsl:for-each select="record">
                  <fo:table-row border-left-style="solid"
                                    border-right-style="solid"
                                    border-bottom-style="solid">
                    <fo:table-cell >
                      <fo:block text-align="center"
                                   padding-top="0.5em">
                        <xsl:value-of select="date"/>
                      </fo:block>
                    </fo:table-cell>
                    <fo:table-cell >
                      <fo:block text-align="center"
                                   padding-top="0.5em">
                        <xsl:value-of select="earnings"/>
                      </fo:block>
                    </fo:table-cell>
                  </fo:table-row>
                </xsl:for-each>

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

        </fo:flow>
      </fo:page-sequence>
    </fo:root>
  </xsl:template>
</xsl:stylesheet>

Гэта выглядае на шмат складаней, чым насамрэч. Мы разбіць яго.

Як і любы іншы дакумент XML, мы павінны дырэктывы препроцессора кажуць так:

 <? XML версіі = "1,0" кадоўка = "ISO-8859-1"?> 

Тады мы стварылі стандартны дакумент стыляў XSLT.

 <XSL: стыляў версіі = "1,0"
        XMLNS: для = "http://www.w3.org/1999/XSL/Format"
        XMLNS: XSL = "http://www.w3.org/1999/XSL/Transform"> 

Розніца тут у тым, што мы ў тым ліку для імёнаў, а таксама XSL.

Наступныя мы які гаворыцца працэсара мы жадаем выйсце XML-дакумент з гэтай

 <xsl:output method="xml" version="1.0" indent="yes" encoding="UTF-8"/> 

А потым мы стварылі галоўнага шаблону XSL для апрацоўкі:

 <xsl:template match="mydata"> 

Звернеце ўвагу, што мы не саступаюць з каранёвым элементам файла XML.

Зараз мы пачынаем XSL-FO частка:

 <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> 

XSL-FO можна вызначыць некалькі макетаў. Напрыклад, вы можаце большасць вашых старонак выкарыстоўваць ЗША фармату ліста ў партрэтную арыентацыю, але некаторыя старонкі выкарыстоўваць альбомную арыентацыю. Для вызначэння гэтых макетаў, а затым высылацца на іх пазней. У нашым прыкладзе мы вызначаем адну ЗША Ліст старонкі з партрэтнай арыентацыі:

<fo:layout-master-set>
        <fo:simple-page-master  master-name="summarypage"
                              page-height="11in"
                              page-width="8.5in"
                              margin-top="1in"
                              margin-bottom="1in"
                              margin-left="1in"
                              margin-right="1in"
                              >
          <fo:region-body />
        </fo:simple-page-master>
      </fo:layout-master-set>

Вы б дадаць, зараз проста-старонцы майстар-запіс для кожнай старонкі, фармат, які вы жадаеце. Дайце яму “майстар-імя” атрыбут – значэнне адвольна, але павінна быць унікальным ад іншых значэнняў простых старонак-майстар.

Зараз мы ствараем асобнік, выкарыстоўваючы вызначаны фармат старонкі:

 <fo:page-sequence master-reference="summarypage">
        <fo:flow flow-name="xsl-region-body"> 

Странице-паслядоўнасць выкарыстоўваецца майстар-спасылка атрыбут, каб паказаць, якія з нашых макетаў старонак павінен быць скарыстаны.

Кожная старонка-паслядоўнасць можа мець адзін часткі струменя. У гэтым вы можаце стварыць некалькі блокаў, якія вызначаюць, дзе будуць захоўвацца вашы тэксты, малюнкі і г.д.

<!-- Report Header -->
          <fo:block text-align="center"
                    font-size="18pt"
                    font-weight="bold">My Custom PDF Report</fo:block>

          <fo:block text-align="center"
                    font-size="14pt"
                    font-weight="bold"
                    padding-after="0.25in">Showing Some data</fo:block>

Тут мы вызначаем два блока правесці наш загаловак старонкі. Пакладзём таксама наш загаловак тут. Як вы можаце бачыць Ёсць шэраг уласцівасцяў / атрыбутаў для блокаў, якія вызначаюць, як змесціва апрацоўваюцца – па цэнтры, памер шрыфта, водступы і г.д. блок вельмі падобны на DIV у HTML, прынамсі ў канцэпцыі.

Мы набліжаемся да рэалізацыі нашых карыстацкіх дадзеных на месцы. Мы вырашылі выкарыстоўваць табліцы для гэтага, так што наступны блок вызначае табліцу з загалоўкам радка:

<!-- Current Numbers -->
          <fo:block text-align="center"
                    font-size="8pt">

            <fo:table table-layout="fixed" width="100%">
              <fo:table-body>
                <fo:table-row background-color="#000"
                              border-left-style="solid"
                              border-right-style="solid"
                              border-top-style="solid">
                  <fo:table-cell >
                    <fo:block color="#fff"
                                 text-align="center"
                                 padding-top="0.5em"
                                 padding-bottom="0.5em">
                                   Date
                    </fo:block>
                  </fo:table-cell>
                  <fo:table-cell >
                    <fo:block color="#fff"
                                 text-align="center"
                                 padding-top="0.5em"
                                 padding-bottom="0.5em">
                                   Earnings
                    </fo:block>
                  </fo:table-cell>
                </fo:table-row>   

Табліцы заўсёды пачынаецца з табліцы і змесціва выходзіць у табліцы тэл. У XSL-FO, табліц, завуцца “табліцы і подпісы”, так Ёсць іншыя часткі, якія могуць змясціцца ў табліцы, што мы не выкарыстоўваем тут. Астатняя ўсталёўвае радок, а два вочкі табліцы. Мы ўжываюцца мала фарматаванні, каб зрабіць наш загаловак роля выдатных ад дадзеных радкоў.

І зараз мы можам уставіць нашы дадзеныя:

 <xsl:for-each select="record">
           <fo:table-row border-left-style="solid"
                            border-right-style="solid"
                            border-bottom-style="solid">
             <fo:table-cell
               ><fo:block text-align="center"
                                padding-top="0.5em">
                 <xsl:value-of select="date"/>
               </fo:block>
             </fo:table-cell>
             <fo:table-cell >
               <fo:block text-align="center"
                            padding-top="0.5em">
                 <xsl:value-of select="earnings"/>
               </fo:block>
            </fo:table-cell>
          </fo:table-row>
        </xsl:for-each>

Мы выкарыстоўваем звычайных пераўтварэнняў XSL сказаць, што для кожнай запісы элемента ў наш файл XML, які мы жадаем дадаць радкі табліцы, якая ўтрымоўвае два вочкі. Гэтыя два вочкі ўтрымоўваюць значэнні даты і прыбытак элементы для запісу.

І ўсё, што засталося зрабіць, гэта зачыніць усе нашы элементы:

 </fo:table-body>
            </fo:table>
          </fo:block>
        </fo:flow>
      </fo:page-sequence>
    </fo:root>
  </xsl:template>
</xsl:stylesheet>

3. Налада FOP

Пераканаецеся, што ў вас усталявана Java (“Sudo APT-атрымаць усталёўку сонечных java6-JRE” на Ubuntu).

Абнаўленне: FOP зараз даступная ў рэпазітары Ubuntu. Такім чынам, “Sudo APT-атрымаць усталёўку FOP” усё, што трэба рабіць. Калі гэта ставіцца да вас, пераходзіце да кроку № 4 ніжэй пасля ўсталёўкі FOP.

Далей вам трэба запампаваць бінарныя (калі вы жадаеце скампіляваць з зыходных тэкстаў) для FOP. Захопіце. Tar.gz файл для апошняй версіі аднаго з люстэркаў. У наш час ён знаходзіцца ў версіі 0,94. (Мы рэкамендуем FOP-0,94-бэн-jdk1.4.tar.gz файл)

Пасля таго як вы, што запампаваў, вынікайце інструкцыям знайсці ў Форум для яго налады. Мы наладзіць яго для глабальнага выкарыстання, так што нашы сцэнары маглі б проста назваць “Фат” каманду туды, дзе яны.

4. У тэставага запуску

Як корань, увядзіце наступную каманду:

 fop -XML test.xml-XSL-test.xsl PDF test.pdf 

Замяніць test.xml, test.xsl, і test.pdf каб яны адпавядалі вашым файлам. Test.xml наш узор XML. Test.xsl з’яўляецца XSL-FO файл мы апісалі вышэй. І test.pdf з’яўляецца выходны файл.

Калі ўсё пойдзе добра, вы будзеце вернутыя да каманднага радка без якіх-небудзь паведамленняў. Калі гэта не так добра, вы ўбачыце адзін з трох выглядаў прадукцыі. Першы тып, дзе вы ўвялі каманду няправільна ці ўваходны файл не існуе – вам будзе прадстаўлена выкарыстанне звалкі для FOP. Другі тып інфармацыйна – вы атрымліваеце некалькі паведамленняў, якія кажуць вам, што адбываецца, ці папярэджанняў пра ўтрыманне перапоўнены іх блокаў. Трэці тып прадукцыі, дзе ў вас ёсць памылка ў XML ці XSL-FO. Чытайце ўважліва паведамленні – яны скажуць вам, што гэта няправільна, але гэта можа быць цяжка знайсці, пакуль вы абвыкнеце да гэтага. Я выявіў, паведамленні пра памылкі прама наперад, і карысна.

Вы павінны ў выніку файл PDF, які выглядае прыкладна так малюнак:

Ці параўнаць з спароджанай PDF.

Для тых, хто Цікаўна, што выява была створаны з дапамогай FOP непасрэдна:

 fop -XML test.xml-XSL test.xsl-PNG test.png 

Усё, што змянілася аргумент-PDF быў заменены-PNG. (Я сапраўды пачынаю кахаць гэту прыладу!)

5. Аўтаматызаваць

Для разавых, тэставанне тыпу працоўных месцаў, нам не трэба ісці далей. Але каб скарыстацца гэтым, мы павінны ўжываць дадзеныя дынамічна і ствараць PDF “на лёце”. Выкарыстанне PHP, гэта лёгка зрабіць. Наш алгарытм можа быць:

  1. Process Data
  2. Create XML
  3. Create PDF

Мы мяркуем, што вы ведаеце, як апрацоўваць дадзеныя і ствараць XML-файлы, бо гэта вельмі моцна залежыць ад вашых уласных патрэб. Мы таксама меркаваны, што вы ручны XSL-FO файл, і / ці стварылі адзін дынамічна ў “Стварыць XML” фазу. Апошнім крокам з’яўляецца тое, што мы зацікаўлены

У маім выпадку мне трэба было стварыць запланаванае заданне для стварэння PDF. Так што я вырашыў зрабіць гэта з дапамогай каманднага радка PHP скрыпт, які адкрываецца праз хрон.

We need to execute a shell command to create our PDF. This looks like

  $cmd = "fop";
  $cmd .= " -xml ". $xmlfile;    //the xml file to apply the template to
  $cmd .= " -xsl ". $xslfoFile;  //the xsl-fo file to do the transformations
  $cmd .= " -pdf ". $pdffile;    //the pdf file to create

  shell_exec($cmd);

З shell_exec час магіі лініі.

Зараз, відавочна, працуе каманда абалонкі з кода можа быць небяспечным. Ёсць куча Гоча асяроддзе абалонкі выканання каманд, а затым рэгулярныя мае рацыю доступу да файлаў уступаюць у гульню. Калі карыстач ваш скрыпт працуе, бо не маюць дазволы на чытанне ўваходных файлаў, ці запісы ў выходны файл, вы можаце цалкам разлічваць каманда на правал. Ваш PHP асяроддзе павінна быць наладжана для апрацоўкі каманды абалонкі, а таксама. Калі вы спрабуеце гэта зрабіць на вэб-хостынгу, вы, верагодна, не павезла – бо вы, верагодна, былі не ў стане ўсталёўваць FOP або. Калі вы трапляеце ў гэту групу пазней, праверыць PHP PDF падтрымкі.

Зараз у вас ёсць PDF генеруецца дынамічна.

Зняволенне

Я знаходжу рашэнне FOP быць вельмі магутным, і стварае прафесійна якія выглядаюць справаздачы. Я толькі павярхоўна, што ён можа зрабіць, але можна ўжо сказаць, што гэта стала каштоўны прадмет у маёй кадаванні арсенале прыёмаў.

Калі вы знайшлі гэты артыкул карыснай, дайце мне ведаць. А яшчэ лепш, дашліце мне спасылку на адзін з вашых файлаў PDF да паведамлення.

Comments are closed.