Scribus XML using Scripter: Difference between revisions

From Scribus Wiki
Jump to navigation Jump to search
Line 44: Line 44:
                         elif (ord(char) == 27):
                         elif (ord(char) == 27):
                             char = chr(10)
                             char = chr(10)
                         elif (ord(char) == 38):
                         elif (ord(char) == 38): # char(38) = '&'
                             char = '&' # note that this should be '&' + 'a' + 'm' + 'p' + ';' this doesn't display properly in the wiki
                             char = '&' # note that this should be '&' + 'a' + 'm' + 'p' + ';' this doesn't display properly in the wiki
                         elif ((ord(char) == 13) or (ord(char) == 10)):
                         elif ((ord(char) == 13) or (ord(char) == 10)):

Revision as of 21:03, 1 November 2013

One of the issues that very quickly was noticeable with using a modified SLA file as in Scribus files as XML was the realization that PAGEOBJECTS in an SLA file are appended at the end of the file as they are created. There is an attribute, OwnPage, that tells which page the object is placed on. Even though there might be a trend to add objects in sequence with the pages, it isn't unusual sometime near the end of the layout process to add something up front. This can be overcome (most likely), but requires a lot more logic in the XSL file.

Scripter, of course has a LOT of access to document and object information, thus this idea was born.

export2xml.py

This is a work-in-progress, so expect it to change as new features are added.

#!/usr/bin/env python
# File: export2xml.py - Extracts the content from a document, saving to an xml file
# 2013.10.29 Gregory Pittman
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

import scribus


def exportText(textfile):
    page = 1
    pagenum = scribus.pageCount()
    T = []
    content = []
    T.append('<?xml version="1.0" encoding="UTF-8"?>\n')
    T.append('<?xml-stylesheet type="text/xsl" href="scribus.xsl"?>\n')
    T.append('<document>\n')
    T.append('<version>Scribus ' + str(scribus.scribus_version_info[0]) + '.' + str(scribus.scribus_version_info[1]) + '.' + str(scribus.scribus_version_info[2]) + str(scribus.scribus_version_info[3]) + '</version>\n')
    while (page <= pagenum):
        scribus.gotoPage(page)
        pagesize = scribus.getPageSize()
        d = scribus.getPageItems()
        strpage = str(page)
        T.append('<page number="'+ strpage + '">\n')
        for item in d:
            if (item[1] == 4):
                filtered = '<para>'
                contents = scribus.getAllText(item[0])
                if (contents in content):
                    contents = ''
                else:
                    for char in contents:
                        if (ord(char) == 28):
                            char = ' '
                        elif (ord(char) == 27):
                            char = chr(10)
                        elif (ord(char) == 38): # char(38) = '&'
                            char = '&' # note that this should be '&' + 'a' + 'm' + 'p' + ';' this doesn't display properly in the wiki
                        elif ((ord(char) == 13) or (ord(char) == 10)):
                            char = "</para><para>"
                        filtered = filtered + char
                    contents = filtered
                T.append('<object type="text">' + contents + '</para>\n')
                T.append('</object>\n')
                content.append(contents)
            elif (item[1] == 2):
                imgname = scribus.getImageFile(item[0])
                imgsize = scribus.getSize(item[0])
                picwidth = int(700 * imgsize[0]/pagesize[0])
                T.append('<object type="image" width="' + str(picwidth) + 'px" source="' + imgname + '">' + imgname + '</object>\n')
                
        T.append('</page>\n')
        page += 1
    T.append('</document>\n')
    output_file = open(textfile,'w')
    output_file.writelines(T)
    output_file.close()
    endmessage = textfile + ' was created'
    scribus.messageBox("Finished", endmessage,icon=0,button1=1)


if scribus.haveDoc():
    textfile = scribus.fileDialog('Enter name of file to save to', \
                                  filter='XML Files (*.xml);;All Files (*)')
    try:
        if textfile == '':
            raise Exception
        exportText(textfile)
    except Exception, e:
        print e

else:
    scribus.messageBox('Export Error', 'You need a Document open, and a frame selected.', \
                       icon=0, button1=1)

The starting point was to generate pseudopages (this is all just one big webpage) by using the table tags to map out a space. By using page dimensions, a proportionally-sized area could be made based on an arbitrary width of 900px, with the plan to have additional tables inside for objects.

Some initial issues

Similar to the overall object-ordering problem in a SLA file, each page numbers frames as you add them, so as you make a list of page objects, this order is created, but this is at least a smaller problem than ordering objects from many different pages. My plan is to use the getPosition data on objects to then sort them – after that, the trick is to use some positioning method. Presently, I still haven't decided whether to use CSS or some other method to try to semi-accurately position objects on the table page space.

In contrast to using an SLA file, the output from Scripter with text frames may not be XML-compliant. For example, the '&' character comes out as that character. The answer is to send it to XML as &amp; instead. I suspect I will discover other characters that need similar treatment.

Another issue is tabs, which come out as a Ctrl-something-inscrutable character. So far, I have simply deleted these.

Next is the issue with CR/nextline characters, which come out as ASCII 10 or 13. Taking a cue from the SLA files, I instead create a para tag to handle this, to create p tags.

At this point, the script works, but only handles text and image frames. No usage of style information is present, as of yet. It does work with both Scribus 1.4.3 and 1.5.0svn.

scribus.xsl

This is not the same as the one used to convert the modified SLA/XML files, so watch the naming not only here, but also in the script above, and change as needed. Note that the background of the webpage is a grey, while the background of the document "pages" is white.

<?xml version="1.0" encoding="utf-8"?>

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

    <html>
    <body bgcolor="#eeeeee">
      <xsl:for-each select="document">
	<h3>This document was created using <xsl:value-of select="version" /></h3>
	<xsl:for-each select="page">
	  <table border="1" cellspacing="0" bgcolor="ffffff">
	    <tr><td width="900px" height="1160px" valign="top">
	  <p><strong>Page <xsl:value-of select="@number" /></strong></p>
	  <xsl:for-each select="object">
	    <xsl:if test="(@type='text')">
	      <table border="0">
		<tr><td width="20px"></td><td>
		<xsl:for-each select="para">
		  <p><xsl:value-of select="." /></p>
		</xsl:for-each></td></tr>
	      </table>
	    </xsl:if>
	    <xsl:if test="@type='image'">
	      <table border="0" style="position: relative; left: 150;">
		<tr><td width="20px"></td><td><img src="{@source}" width="{@width}" /></td></tr>
	      </table>
	    </xsl:if>
	  </xsl:for-each>
	  </td></tr>
	</table>
	</xsl:for-each>
      </xsl:for-each>
    </body>
    </html>
  </xsl:template>
</xsl:stylesheet>