Page 1 of 1

[Solved] Create ODT with PHP

Posted: Sat Jan 19, 2008 3:14 pm
by noscollections
Hello,

I have a PHP soft and I would like have an export for openoffice (ODT)

I have search the web for do this and I found :

1. http://php.developpez.com/faq/?page=ooo
work find but only for text.
I woulf like page break, and image (link)

2. http://phpdocwriter.sourceforge.net/
but it create openoffice 1.1 file (.sxw) and openoofice 2.x open only file with text with repare. And don't work with php5

3. tinybut strong, not tested but it look not easy.

Is anyone have do something like this ?

create odt, with text, image link, page break and why not more ?

Thanks for your experience help

french my english is not perfect.

Re: Create ODT with PHP

Posted: Sat Jan 19, 2008 3:58 pm
by TerryE
First, remember that ODF is primarily a ZIP compressed container containing a bunch of XML encoded files so any XLST transformation engine can be coopted to do most of this. For example: ODF-XSLT Document Generator and the engine within OpenXML/ODF Translator Add-ins for Office.

Also its pretty trivial rolling your own ODT/ODS if what you are really doing is generating proforma test reports as you can create a baseline with Writer or Calc then use php effectively as a macro generator create you specific contents.xml.

Re: Create ODT with PHP

Posted: Wed Jan 23, 2008 10:37 am
by noscollections
Hello,

I have create an odt file with OOO.
The file contained only pages break text, page break, text.

My goal is to find xml code of texte and page break.

I have find the text code, but nothing particular between text code that could be page break code. I edit contents.xml file.

I have found the image link code. it's a long code, I try to make the same but OOO show nothing.

The script here : http://php.developpez.com/faq/?page=ooo is good, because it create a real odt file. it zip the contents.xml and manifest.xml files and write odt on the server

I can't find doc that explain how odt file is made.

Re: Create ODT with PHP

Posted: Wed Jan 23, 2008 3:18 pm
by TerryE
The ODF spec is in fact referenced in the SDK. I was going to look it up for you, but just do a Google on "ODF specification" and it will be the first hit. The easiest way to understand the content of an OTD is to create a mash-up of the sort of file that you want to create and look at the content. So to work out how page breaks worked I created a document Asd<ctl+enter>sdas, saved it, opened it with Winzip and looked at the content.xml. This defined a style:
  • <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Standard">
    <style:paragraph-properties fo:break-before="page" />
    </style:style>
and the bound this to the text sdas:
  • <text:p text:style-name="P1">sdas</text:p>
That's how page breaks work.

Of course for this to work you will need php5 together with the XML and ZIP modules installed on your server. I've got these on my test rig. At the moment our user.services.OpenOffice.org doesn't have these modules installed for example. My hobby shared service is still on php4!

However I am currently writing a tutorial on Integrating OOo apps with Server application and I will cover this subject here.

Re: Create ODT with PHP

Posted: Fri Jan 25, 2008 3:18 pm
by noscollections
Hello,

Yes, That work.
I have do like you, but I not see a new style was create.

I have create a style and Insert the xml code and, that work perfect.

For my other probleme (image link), I will look the SDK doc, by a search by google.

I will post message soon, to ask you, if I found, I will told you.

Thanks Terry E

Re: Create ODT with PHP

Posted: Sat Jan 26, 2008 11:20 am
by noscollections
Hello,

I have do a test, I have create a simple odt with image link.

here is the that I think, is for image link :

1. style :

Code: Select all

<style:style style:name="fr1" style:family="graphic" style:parent-style-name="Graphics">
<style:graphic-properties style:mirror="none" fo:clip="rect(0cm 0cm 0cm 0cm)" draw:luminance="0%" draw:contrast="0%" draw:red="0%" draw:green="0%" draw:blue="0%" draw:gamma="100%" draw:color-inversion="false" draw:image-opacity="100%" draw:color-mode="standard"/>
</style:style>
2. in the text

Code: Select all

<text:p text:style-name="Standard">
<draw:frame draw:style-name="fr1" draw:name="Image1" text:anchor-type="paragraph" svg:width="16.999cm" svg:height="12.748cm" draw:z-index="0">
<draw:image xlink:href="CASERNE_POLICE.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" draw:filter-name="<Tous les formats>"/>
</draw:frame>
</text:p>
Part code that I have in my odt that I have in content.xml creat by php :

1. style :

Code: Select all

<style:style style:name="fr1" style:family="graphic" style:parent-style-name="Graphics">
<style:paragraph-properties style:mirror="none" fo:clip="rect(0cm 0cm 0cm 0cm)" draw:luminance="0%" draw:contrast="0%" draw:red="0%" draw:green="0%" draw:blue="0%" draw:gamma="100%" draw:color-inversion="false" draw:image-opacity="100%" draw:color-mode="standard"/>
</style:style>
2. in the doc :
"text that I see"

Code: Select all

<text:p text:style-name="Standard">
<draw:frame draw:style-name="fr1" draw:name="Image1" text:anchor-type="paragraph" svg:width="16.999cm" svg:height="12.748cm" draw:z-index="0">
<draw:image xlink:href="CASERNE_POLICE.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" draw:filter-name="<Tous les formats>"/>
</draw:frame>
</text:p>
"text that I see"


---
During I 'm wrting this post I see just that style "standard" that is show here : <text:p text:style-name="Standard">
is not in my style.
It is in my OOO geneted file in the style.xml but not in my own ODT.

I will Add it for test. Except this I not see what is the probleme.

---
However I am currently writing a tutorial on Integrating OOo apps with Server application and I will cover this subject here.
This is a good news, I will be to read it when it will be ready. Don't forget to inform us when it will be on the web.

Re: Create ODT with PHP

Posted: Sat Jan 26, 2008 11:43 am
by noscollections
It's me again

image is not show, I don't know why, I will search again. I must forget something but where ??? that is the question !

I post my content.xml code ( I have add line break in the code for make it read easier)

Code: Select all

<?xml version="1.0" encoding="utf-8"?><office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0">
<office:automatic-styles>
<style:style style:name="tests" style:family="text">
<style:text-properties fo:font-family="Courier new" fo:font-weight="bold" fo:font-style="italic" fo:color="#336699" fo:background-color="#66CCFF" style:text-underline-type="single"/>
</style:style>
<style:style style:name="tests2" style:family="text">
<style:text-properties fo:font-family="Courier new" fo:font-weight="" fo:font-style=""/>
</style:style>	

<style:style style:name="Standard" style:family="text" style:class="text"/>
<style:style style:name="P1" style:family="paragraph" style:parent-style-name="Standard">
<style:paragraph-properties fo:break-before="page"/>
</style:style>
<style:style style:name="fr1" style:family="graphic" style:parent-style-name="Graphics">
<style:paragraph-properties style:mirror="none" fo:clip="rect(0cm 0cm 0cm 0cm)" draw:luminance="0%" draw:contrast="0%" draw:red="0%" draw:green="0%" draw:blue="0%" draw:gamma="100%" draw:color-inversion="false" draw:image-opacity="100%" draw:color-mode="standard"/>
</style:style>

</office:automatic-styles>
<office:body>
<office:text>
<text:p>
<text:span text:style-name="tests">mis en forme</text:span>
</text:p> 

<text:p>
<text:span text:style-name="tests2">mis en forme 2</text:span>
</text:p>

<text:p>Hello world! text must be after HERE</text:p>

<text:p text:style-name="Standard">
<draw:frame draw:style-name="fr1" draw:name="Image1" text:anchor-type="paragraph" svg:width="16.999cm" svg:height="12.748cm" draw:z-index="0">
<draw:image xlink:href="CASERNE_POLICE.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" draw:filter-name="<Tous les formats>"/>
</draw:frame>
</text:p>

<text:p>Hello world! text must be BEFORE HERE</text:p>
<text:p text:style-name="P1">
<text:span text:style-name="tests2">mis en forme 3</text:span></text:p>
</office:text></office:body></office:document-content>

Re: Create ODT with PHP

Posted: Sat Jan 26, 2008 12:43 pm
by TerryE
The XML has to be well formed. A good check on whether it is well formed or not is to load it into your favourite browser.
In this case you've introduced extra elements with declaring their grammar / namespaces. You need to add the following attributes to the office:document-content tag:
  • xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
    xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
    xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
    xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
    xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
    xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
I found this out the hard way by binary chop.

I substituted the image with one of mine and this then loaded in Writer on my PC. As I said, the easiest way to create a document is to use writer in the first place and then retro-engineer your automated document from this.

Re: Create ODT with PHP

Posted: Sat Jan 26, 2008 4:18 pm
by noscollections
That's OK, it work.

I found an other probleme : it's "../CASERNE_POMPIERS.jpg" and not "CASERNE_POMPIERS.jpg" for external link in the same directory od the odt file

I will optimise the php code of my test file and poste the php code.

thank's Terry E

Re: [Solved] Create ODT with PHP

Posted: Wed Feb 13, 2008 10:14 am
by noscollections
Hello,

With all the informations I have collected, I have done a php script, not really a class, to make an odt with php (5)

You need the file file odt_gen.php for the functions.
After I post an exemple of script that do an odt. the odt file is a real odt, it is zipped.

note : the image are link so when you open the odt file, break the link and OOO will includ them in the odt file

file odt_gen.php

Code: Select all


<?php


// PAGE BREAK
// -----

function pagebreak(){
global $content;
global $XMLParagraph;
global $XMLOfficeText;
$XMLParagraph = $content->createElement('text:p');
$XMLParagraph->setAttribute('text:style-name', 'P1');
$XMLOfficeText->appendChild($XMLParagraph);
}


// SAUT DE LIGNE
// -----

function br(){
global $content;
global $XMLParagraph;
global $XMLOfficeText;
$XMLParagraph = $content->createElement('text:p');
$XMLOfficeText->appendChild($XMLParagraph);
}


// TEXTE SIMPLE
// -----

function texte($text){
$Caracs = array("&" => "&",  "e" => "e");
$text=strtr($text, $Caracs);

global $XMLText;
global $content;
global $XMLOfficeText;
$XMLText = $content->createElement('text:p', utf8_encode($text));
$XMLOfficeText->appendChild($XMLText);
}

// TEXT et STYLE
// -----

function textestyle($text,$style_name){
$Caracs = array("&" => "&",  "e" => "e");
$text=strtr($text, $Caracs);

global $XMLText;
global $content;
global $XMLParagraph;
$XMLText = $content->createElement('text:span', utf8_encode($text));
$XMLText->setAttribute('text:style-name', $style_name);
$XMLParagraph->appendChild($XMLText);
}


// IMAGE
// -----

function image($href,$style_name="fr1",$name="Image1", $anchor_type="paragraph" ,$x,$y , $width , $height ){
global $XMLdraw;
global $content;
global $XMLParagraph;
global $XMLimage;
global $XMLOfficeText;
// print $x."-".$y;
 



$XMLdraw = $content->createElement('draw:frame');
$XMLdraw->setAttribute('draw:style-name', $style_name);
$XMLdraw->setAttribute('draw:name', $name);
$XMLdraw->setAttribute('text:anchor-type', $anchor_type);
$XMLdraw->setAttribute('svg:x', $x.'cm');
$XMLdraw->setAttribute('svg:y', $y.'cm');
$XMLdraw->setAttribute('svg:width', $width.'cm');
$XMLdraw->setAttribute('svg:height', $height.'cm');
$XMLdraw->setAttribute('draw:z-index', '0');
$XMLParagraph->appendChild($XMLdraw);

$XMLimage = $content->createElement('draw:image');
$XMLimage->setAttribute('xlink:href', $href);
$XMLimage->setAttribute('xlink:type', 'simple');
$XMLimage->setAttribute('xlink:show', 'embed');
$XMLimage->setAttribute('xlink:actuate', 'onLoad');
$XMLimage->setAttribute('draw:filter-name', '<Tous les formats>');
$XMLdraw->appendChild($XMLimage);

}

















//--------------------------------------
// --------DOC INIT --------------------

function odt_init(){
global $manifest;
global $XMLManifest;
global $XMLFileEntry;




$manifest = new DOMDocument('1.0', 'utf-8');

$XMLManifest = $manifest->createElement('manifest:manifest');
$XMLManifest->setAttribute('xmlns:manifest', 'urn:oasis:names:tc:opendocument:xmlns:manifest:1.0');
$manifest->appendChild($XMLManifest);

$XMLFileEntry = $manifest->createElement('manifest:file-entry');
$XMLFileEntry->setAttribute('manifest:media-type', 'application/vnd.oasis.opendocument.text');
$XMLFileEntry->setAttribute('manifest:full-path', '/');
$XMLManifest->appendChild($XMLFileEntry);

$XMLFileEntry = $manifest->createElement('manifest:file-entry');
$XMLFileEntry->setAttribute('manifest:media-type', 'text/xml');
$XMLFileEntry->setAttribute('manifest:full-path', 'content.xml');
$XMLManifest->appendChild($XMLFileEntry);



global $content;
global $XMLOfficeContent;

$content = new DOMDocument('1.0', 'utf-8');


$XMLOfficeContent = $content->createElement('office:document-content');
$XMLOfficeContent->setAttribute('xmlns:office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0');
$XMLOfficeContent->setAttribute('xmlns:text', 'urn:oasis:names:tc:opendocument:xmlns:text:1.0');
$XMLOfficeContent->setAttribute('xmlns:fo', 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0');
$XMLOfficeContent->setAttribute('xmlns:style', 'urn:oasis:names:tc:opendocument:xmlns:style:1.0');
$XMLOfficeContent->setAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/');
$XMLOfficeContent->setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
$XMLOfficeContent->setAttribute('xmlns:svg', 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0');
$XMLOfficeContent->setAttribute('xmlns:style', 'urn:oasis:names:tc:opendocument:xmlns:style:1.0');
$XMLOfficeContent->setAttribute('xmlns:table', 'urn:oasis:names:tc:opendocument:xmlns:table:1.0');
$XMLOfficeContent->setAttribute('xmlns:draw', 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0');
$XMLOfficeContent->setAttribute('xmlns:meta', 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0');
$XMLOfficeContent->setAttribute('xmlns:number', 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0');
$content->appendChild($XMLOfficeContent); 

global $XMLAutomaticStyles;

$XMLAutomaticStyles = $content->createElement('office:automatic-styles');
$XMLOfficeContent->appendChild($XMLAutomaticStyles);

}



function creat_style($name , $family='text' , $font_family, $font_weight , $font_style , $color , $background_color , $text_underline_type ){
global $content;
global $XMLStyle;
global $XMLAutomaticStyles;
global $XMLTextProperties;

$XMLStyle = $content->createElement('style:style');
$XMLStyle->setAttribute('style:name', $name);
$XMLStyle->setAttribute('style:family', $family);
$XMLAutomaticStyles->appendChild($XMLStyle);

$XMLTextProperties = $content->createElement('style:text-properties');
$XMLTextProperties->setAttribute('fo:font-family', $font_family);
$XMLTextProperties->setAttribute('fo:font-weight', $font_weight);
$XMLTextProperties->setAttribute('fo:font-style', $font_style);
$XMLTextProperties->setAttribute('fo:color', $color);
$XMLTextProperties->setAttribute('fo:background-color', $background_color);
$XMLTextProperties->setAttribute('style:text-underline-type', $text_underline_type);
$XMLStyle->appendChild($XMLTextProperties);

}


function creat_style_img($name ){
global $content;
global $XMLStyle;
global $XMLAutomaticStyles;
global $XMLTextProperties;

$XMLStyle = $content->createElement('style:style');
$XMLStyle->setAttribute('style:name', $name);
$XMLStyle->setAttribute('style:family', 'graphic');
$XMLStyle->setAttribute('style:parent-style-name', 'Graphics');
$XMLAutomaticStyles->appendChild($XMLStyle);  


$XMLTextProperties = $content->createElement('style:graphic-properties');
$XMLTextProperties->setAttribute('style:run-through', 'foreground');
$XMLTextProperties->setAttribute('style:wrap', 'dynamic');
$XMLTextProperties->setAttribute('style:number-wrapped-paragraphs', 'no-limit');
$XMLTextProperties->setAttribute('style:wrap-contour', 'false');
$XMLTextProperties->setAttribute('style:vertical-pos', 'from-top');
$XMLTextProperties->setAttribute('style:vertical-rel', 'paragraph');
$XMLTextProperties->setAttribute('style:horizontal-pos', 'from-left');
$XMLTextProperties->setAttribute('style:horizontal-rel', 'paragraph');
$XMLTextProperties->setAttribute('style:mirror', 'none');
$XMLTextProperties->setAttribute('fo:clip', 'rect(0cm 0cm 0cm 0cm)');
$XMLTextProperties->setAttribute('draw:luminance', '0%');
$XMLTextProperties->setAttribute('draw:contrast', '0%');
$XMLTextProperties->setAttribute('draw:red', '0%');
$XMLTextProperties->setAttribute('draw:green', '0%');
$XMLTextProperties->setAttribute('draw:blue', '0%');
$XMLTextProperties->setAttribute('draw:gamma', '100%');
$XMLTextProperties->setAttribute('draw:color-inversion', 'false');

$XMLTextProperties->setAttribute('draw:image-opacity', '100%');
$XMLTextProperties->setAttribute('draw:color-mode', 'standard');
$XMLStyle->appendChild($XMLTextProperties);

}


function doc_init(){
global $content;
global $XMLOfficeBody;
global $XMLOfficeContent;
global $XMLOfficeText;
global $XMLParagraph;


$XMLOfficeBody = $content->createElement('office:body');
$XMLOfficeContent->appendChild($XMLOfficeBody);

$XMLOfficeText = $content->createElement('office:text');
$XMLOfficeBody->appendChild($XMLOfficeText);

$XMLParagraph = $content->createElement('text:p');
$XMLOfficeText->appendChild($XMLParagraph);

}


?>

Exemple of code to make the odt

Code: Select all

<?php 


// call the function file
include "odt_gen.php";

// ODT init
odt_init();

//styles parameter
creat_style( 'tests' , 'text' , 'Courier new' , 'bold' , 'italic' , '#FF0000' , '#66CCFF' , 'single' );
creat_style( 'titre_a' , 'text' , 'Courier new' , '' , '' , '#FF0000' , '#66CCFF' , 'single' );

// image style
creat_style_img( "fr1" );

// end of style and doc init
doc_init();

// break line
br();

// simple texte without style
texte("Simple texte");

// break line
br();

textestyle("Text with tests2 style","tests2");
textestyle("Text with titre_a style","titre_a");
// note that style must be define in stlyes before


br();

// Image
// paramaters 
// image url  '../image01.jpg ' for an image in the same directory of the php file
// fr1 : style name of the image
// image name
// ancord tyle
// position from the beginig of the paragraph right and down (15,0) in cm
// size of the image width and height in cm
image("../image01.jpg","fr1","Image1","paragraph", 15 , 0 , 3 , 3.5);



//Now creation of the file 'hello-world2.odt' in the same directory of the php file


$document = new ZipArchive();
$document->open('hello-world2.odt', ZIPARCHIVE::OVERWRITE);

$document->addFromString('META-INF/manifest.xml', $manifest->saveXML());
$document->addFromString('content.xml', $content->saveXML());

$document->close();

// juste for be sure the script is finish !					 
print "OK";

?>
I hove that could help some of you

If you add funcionnality, juste complete the post

Chris

Re: [Solved] Create ODT with PHP

Posted: Thu Feb 14, 2008 7:07 pm
by TerryE
Chris, I want to take a proper look at this, so give me a few days. Also, it may be worth you creating a "Code snippet" around this, but we can discuss that offline. :-)

Re: [Solved] Create ODT with PHP

Posted: Fri Mar 14, 2008 3:28 pm
by noscollections
TerryE wrote:Chris, I want to take a proper look at this, so give me a few days. Also, it may be worth you creating a "Code snippet" around this, but we can discuss that offline. :-)
Hello TerryE

I would like work again in my project, I would like to know if you have watch the code and if you have any comment on it.

I prefert work on a good way, and your comments could be good for me.

If need you can contacte me by Private message


Chris

Re: [Solved] Create ODT with PHP

Posted: Mon Mar 24, 2008 1:22 am
by TerryE
Chris, sorry for my delay in getting back to you. A few points:
  • One of the really nice things about OSS code is that their are usually loads of good example templates to work with out there on the net. One example that I came across recently re ODF document creation is in the phpMyAdmin tool. Since this is GPL licensed, you can download and reuse the source from http://www.phpmyadmin.net/home_page/downloads.php. The php modulles that you want are: libraries/opendocument.lib.php, libraries/export/ods.php and libraries/export/odt.php. This also includes examples of other extract formats. Note that this is a more minimal approach in that it doesn't need DOMDocument, ZipArchive but that is understandable in a package which wants to minimise its dependencies on other packages.
  • As a matter of personal preference, I would prefer to us a class container to group together functions that collectively act as methods operating on an entity. In this I would create a ODSdocument class. And functions like pagebreak and br etc. would then become class methods, something like as follows. Note I don't declare globals that really aren't:

    Code: Select all

        function pagebreak(){
            $node = $this->content->createElement( 'text:p' );
            $node->setAttribute( 'text:style-name', 'P1' );
            $this->content->appendChild($node);
        }
    
        function br(){
            $this->content->appendChild(
                $this->$content->createElement('text:p') );
        }
    
        function texte($text, $style_name = ''){
            $node = $this->$content->createElement( 'text:p', 
                utf8_encode( $htmlspecialchars($text) ) ) ;
            if ($style_name != '') {
                $node->setAttribute('text:style-name', $style_name);
            }    
            $this->content->appendChild( $node );
        }
           
  • Another thing which has its pluses and minuses is that I also feel that any language has its own natural style and characteristics. I like to code within them wherever possible, so for example I wouldn't use C coding style in Perl for example, or Java in php. That is one reason that I dislike the DOMDocument implementation. It conforms as much as possible to the standard DOM API which designed to port across many languages such as java and javascript.