Adjust Dita-OT plugin to output PDF wireframe with all blocks solid border - dita-ot

I'm interested to output solid black border surrounding all fo:blocks to aid in viewing where the borders are between elements displayed in a pdf output.
I would like to apply a transformation at the end of dita-ot plugin that applies the borders. I can fiddle with the following xsl however I'm not sure how to apply the xlst at the end of a dita-ot process.
<?xml version='1.0' encoding='UTF-8'?>
<xsl:stylesheet exclude-result-prefixes="xs ditaarch opentopic e" version="2.0" xmlns:ditaarch="http://dita.oasis-open.org/architecture/2005/" xmlns:e="com.docdept.pdf" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:opentopic="http://www.idiominc.com/opentopic" xmlns:opentopic-func="http://www.idiominc.com/opentopic/exsl/function" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="#*|*|processing-instruction()|comment()">
<xsl:copy>
<xsl:apply-templates select="*|#*|text()|processing-instruction()|comment()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="fo:block">
<xsl:copy>
<xsl:copy-of select="#*"/>
<xsl:attribute name="border-style">solid</xsl:attribute>
<xsl:attribute name="border-width">0.5pt</xsl:attribute>
<xsl:attribute name="border-color">black</xsl:attribute>
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I thought perhaps the following to apply wireframe.xsl at the end of the process but this does not work.
<?xml version='1.0' encoding='UTF-8'?>
<plugin id="com.docdept.pdf">
<require plugin="org.dita.pdf2" />
<feature extension="dita.conductor.transtype.check" value="adjust-pdf" />
<feature extension="dita.transtype.print" value="docdept-pdf" />
<feature extension="dita.conductor.target.relative" file="integrator.xml" />
<feature extension="dita.xsl.pdf" file="xsl/fo/wireframe.xsl"/>
</plugin>

I'm seeing that it's better to associate borders of different colors to the attribute sets so there is visual reference that can also be searched for by color name within the fo output.
<xsl:attribute name="border">1mm thin solid</xsl:attribute>
<xsl:attribute name="border-color">GOLD</xsl:attribute>

Related

current-dateTime() to number

I need to convert the current-dateTime() to a number, because the output only allows an integer (or long). How can I do that?
My desired output:
<?xml version="1.0" encoding="utf-8"?>
<currentDate>NaN</currentDate>
My XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" version="2.0">
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:variable name="version" select="'1.0'"/>
<xsl:template match="/">
<xsl:element name="currentDate">
<xsl:value-of select="number(current-dateTime())"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
But I get this here:
<?xml version="1.0" encoding="utf-8"?>
<currentDate>NaN</currentDate>
When I remove the number() I do get the timestamp, but I need to have a clean number.
<?xml version="1.0" encoding="utf-8"?>
<currentDate>2014-01-15T07:01:02.526+01:00</currentDate>
How can I convert the timestamp to a clean number?
As mentioned, to convert "2014-01-15T07:01:02.526+01:00" to "20140115070102526" you can use the translate() function (this would work with XSLT 1.0):
<xsl:value-of select="translate(substring(string(current-dateTime()), 1, 23), '-:T.', '')"/>
Alternatively, you can calculate the duration between the current date and time and an arbitrary start and divide this duration by a millisecond to get the number of milliseconds since that date:
<xsl:value-of select="(current-dateTime() - xs:dateTime('1971-01-01T00:00:00')) div xs:dayTimeDuration('PT0.001S')"/>
In XSLT 2.0, you can use the format-dateTime() function and reformat the date: just use a picture parameter with no separators.
Alternatively - assuming all component values are already padded with zeros to maintain a fixed length - you could simply translate the separator characters away.

How do I enable/use XSLT document function in eclipse?

I am trying to write a XSLT file that will process an Android Activity layout xml file and create an HTML equivalent.
In creating/testing out the xslt file, I am using the eclipse xslt tools.
One of the roadblocks on this path, is that many values are not held in the Android layout file directly (such as string/text values) but are instead held in a seperate xml file located in the 'values' folder
I have been trying to use the xslt function 'document' to open the strings.xml file but without success.
Q) Are there any eclipse permissions that I need to enable to allow the xslt document function to operate?
Q) Is there something missing in my understanding of how the document function should operate?
The line which is contained within the TextView template (in the xslt file) that is trying to access the android strings.xml file, is:
<xsl:value-of select="document('../values/strings.xml')/String[#name=substring-after(#android:text,'/')]" />
The layout file is in the res/layout folder
The xslt is in a res/xsl
folder.
The strings.xml file is in the res/values folder
Here are the code samples:
Android XML Layout snippet:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!-- This is the full screen vertical layout -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="vertical" >
<!-- This is the main content vertical layout -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="#dimen/mainHeadingIndent" >
<!-- This is the Status Section Vertical content layout -->
<TextView
style="#style/HeadingTextStyle"
android:id="#+id/textView2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:text="#string/Status"/>
**The rest of the layout file is intentionally omitted**
Here is the XSLT file:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:android="http://schemas.android.com/apk/res/android">
<xsl:output method="html" version="4.0" encoding="iso-8859-1"
indent="yes" />
<xsl:template match="/">
<html>
<head>
</head>
<body>
<xsl:for-each select="LinearLayout">
<xsl:call-template name="LinearLayout">
</xsl:call-template>
</xsl:for-each>
</body>
</html>
</xsl:template>
<xsl:template name="LinearLayout">
<xsl:variable name="width">
<xsl:value-of select="#android:layout_width" />
</xsl:variable>
<xsl:variable name="height">
<xsl:value-of select="#android:layout_height" />
</xsl:variable>
<xsl:variable name="margin">
<xsl:value-of select="#android:layout_margin" />
</xsl:variable>
<xsl:variable name="orient">
<xsl:value-of select="#android:orientation" />
</xsl:variable>
<xsl:variable name="pos">
<xsl:number value="position()" format="1" />
</xsl:variable>
<div div_pos='{$pos}' Width='{$width}' Height='{$height}' Margin='{$margin}'
Orient='{$orient}'>
<xsl:for-each select="LinearLayout">
<xsl:call-template name="LinearLayout">
</xsl:call-template>
</xsl:for-each>
<xsl:for-each select="TextView">
<xsl:call-template name="TextView">
</xsl:call-template>
</xsl:for-each>
<xsl:for-each select="ImageButton">
<xsl:call-template name="ImageButton">
</xsl:call-template>
</xsl:for-each>
<xsl:for-each select="Spinner">
<xsl:call-template name="Spinner">
</xsl:call-template>
</xsl:for-each>
<xsl:for-each select="Button">
<xsl:call-template name="Button">
</xsl:call-template>
</xsl:for-each>
</div>
</xsl:template>
<xsl:template name="ImageButton">
<div id="{#android:id}">
<xsl:comment>
ImageButton
</xsl:comment>
</div>
</xsl:template>
<xsl:template name="TextView">
<xsl:variable name="pos">
<xsl:number value="position()" format="1" />
</xsl:variable>
Text field =
<xsl:value-of select="#android:text" />
<xsl:variable name="txt">
<xsl:choose>
<xsl:when test="contains(#android:text,'/')">
<xsl:value-of select="document('../values/strings.xml')/String[#name=substring-after(#android:text,'/')]" />
<!--
<xsl:value-of select="substring-after(#android:text,'/')" />
-->
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="#android:text" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<div id="{#android:id}">
<xsl:comment>
TextView Element
</xsl:comment>
<p>
Text pointer is: <xsl:value-of select="$txt" />
</p>
<!-- <p>Text pointer is:<xsl:copy-of select="$txt"/></p> <xsl:value-of
select="document('../values/strings.xml')/String[#name=$txt]" />
<xsl:value-of select="substring-after(#android:text,'/')" />
-->
</div>
endoftext
<br />
</xsl:template>
<xsl:template name="Spinner">
<div id="{#android:id}">
<xsl:comment>
Spinner
</xsl:comment>
</div>
</xsl:template>
<xsl:template name="Button">
<div id="{#android:id}">
<xsl:comment>
Button
</xsl:comment>
</div>
</xsl:template>
</xsl:stylesheet>
You need to include the document's root element in the XPath (this is very easy to forget):
<xsl:value-of select="document('../values/strings.xml')/*/String[#name=substring- after(#android:text,'/')]" />
Well, I've solved it.
The big issue is that when xslt fails, it generally fails silently .... ie no errors
The issue turned out not to be the document function per-se. It was the selection criteria that followed the document function. This had a problem such that there was no selected nodes and hence no output from the statement. This all made it look like the document function was not working.
The big change was that the substring-after clause wasn't/isn't being evaluated against the the right attribute. By splittingg the substring clause up, it started to work.
As they say, it's "FM" (flipping magic)!
Here is what I replaced the document line with:
<xsl:variable name='string_value'>
<xsl:value-of select="substring-after(#android:text,'/')" />
</xsl:variable>
<xsl:value-of select="$string_value"/>
<xsl:value-of select="document('../values/strings.xml')/*/string[#name=$string_value]"/>
This sucessfully pulled the correct value out of the strings.xml file.

Stripping empty tags from Plone content with Diazo

I have a Plone site, themed with plone.app.theming. The problem I have is that the design is quite strict and doesn't assume any empty <p> elements or any other nonsense TinyMCE outputs. Such elements break the intended design. So I want to strip the empty elements from the content. I have tried inline xslt (that, according to http://diazo.org/advanced.html#inline-xsl-directives should be supported) like:
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(*) and not(text()[normalize-space()])]"/>
But it didn't do the trick. In fact it made something weird. The empty p tags that I wanted to get rid of stayed intact but some other elements like
<img src="../++theme++jarn.com/whatever.png" />
turned into
with the image being striped out. Replacing match="*[… in the second template to match="p[… didn't strip out the images, but those nasty <p> were still in the output.
Any hints on how to get rid of the empty elements using Diazo rules?
UPDATE January 31, 2012
Here is the content from which I need the empty p tags to be stripped off:
<div id="parent-fieldname-text">
<p></p>
<p> </p>
<p> </p>
<p><section id="what-we-do">
<p class="visualClear summary">Not empty Paragraph</p>
<ul class="thumbsList">
<li> <img src="../++theme++jarn.com/whatever.png" /></li>
<li> <img src="../++theme++jarn.com/whatever.png" /></li>
</ul>
</section></p>
</div>
The Diazo transformation rules:
<?xml version="1.0" encoding="UTF-8"?>
<rules
xmlns="http://namespaces.plone.org/diazo"
xmlns:css="http://namespaces.plone.org/diazo/css"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p[not(*) and not(normalize-space())]"/>
<!-- The default theme, used for standard Plone web pages -->
<theme href="index.html" css:if-content="#visual-portal-wrapper" />
<replace css:theme-children="div.contentWrapper" css:content-children="#content" />
</rules>
The output I get after applying the transformations to the Plone site is absolutely identical to the input while I would expect to get those 3 empty <p> tags after opening <div> to go away.
If I change the second template to match all elements like match="*… then the images get stripped out, but the empty <p> tags are still there.
Just have this:
<xsl:template match="p[not(*) and not(normalize-space())]"/>
A complete transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p[not(*) and not(normalize-space())]"/>
</xsl:stylesheet>
when this transformation is applied on this XML document:
<div>
<p/>
<p> </p>
<p><img src="..."/></p>
<img src="..."/>
</div>
the wanted, correct result is produced:
<div>
<p>
<img src="..."/>
</p>
<img src="..."/>
</div>
Works for me. I've added an example of using Dimitre's xpath in a drop content rule at https://github.com/plone/diazo/commit/94ddff7117d25d3a8a89457eeb272b5500ec21c5 but it also works as the equivalent xsl:template. The example is pared down to the basics but it works using the complete example content in the question too.

XSLT2 doesn't import user functions?

I've just found that if main.xsl xsl:imports lib.xsl which defines some XSLT2 functions, those functions can't be used in main.xsl.
Error: There's no function in namespace http://foo.bar/my-library-ns
However, xsl:include does import those functions.
This is no reproducible
This stylesheet:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:local="http://localhost/">
<xsl:import href="lib.xsl"/>
<xsl:template match="/">
<xsl:value-of select="local:function()"/>
</xsl:template>
</xsl:stylesheet>
With this imported module:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:local="http://localhost/"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:function name="local:function" as="xs:boolean">
<xsl:sequence select="true()"/>
</xsl:function>
</xsl:stylesheet>
Output*:
true
* Tested on Saxon and Altova. (My XQSharp has expired...)
I've just found that if main.xsl
xsl:imports lib.xsl which defines some
XSLT2 functions, those functions can't
be used in main.xsl
Of course, this isn't true.
Do have a look at the FXSL library, whose templates contain functions that must be imported by the using XSLT code. The stylesheet modules of FXSL in fact import other stylesheet modules and use their functions.
Here is a simple example:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
exclude-result-prefixes="f"
>
<xsl:import href="../f/func-foldl.xsl"/>
<xsl:import href="../f/func-Operators.xsl"/>
<!--
This transformation calculates 10!
Expected result: 3628800 or 3.6288E6
-->
<xsl:output encoding="UTF-8" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:value-of select="f:foldl(f:mult(), 1, 1 to 10 )"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on any XML document (not used), it calculates the 10! (10 factorial) value:
3628800
All three XSLT 2.0 processors I am working with: Saxon 9, AltovaXML and XQSharp produce this same result.
Here is a partial view at the import hierarchy of the above transformation:
As we can see, only less than half of all imports are shown... :)
Of course here we only see the imported templates, but in every imported stylesheet module, for every template there are at least two <xsl:function>s.

XSL Transform - Remove Parent Node

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:enterprise.soap.sforce.com">
<soapenv:Body>
<upsertResponse>
<result>
<created>true</created>
<id>0011</id>
<success>true</success>
</result>
<result>
<created>false</created>
<id>0012</id>
<success>true</success>
</result>
</upsertResponse>
</soapenv:Body>
</soapenv:Envelope>
**How can I transform this to**
<upsertResponse>
<result>
<created>true</created>
<id>0011</id>
<success>true</success>
</result>
<result>
<created>false</created>
<id>0012</id>
<success>true</success>
</result>
</upsertResponse>
This is an example of XSL that takes the first child of first child of root and makes it root node of new XML:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:copy-of select="./*[1]/*[1]/*[1]" />
</xsl:template>
</xsl:stylesheet>
Please note that you can take only one node and not multiple nodes since placing few nodes as root of XML is not valid.
Use an <xsl:match> to select the <upsertResponse> element, then put an <xsl:copy> inside of it. That should do the trick. Sorry I don't have the exact syntax, but hopefully this points you in the right direction.