XSL - Check if select has no text nodes then show "Not Results" - testing

How can I check if my block/select has no text nodes then show "Not Results"
<xsl:choose>
<xsl:when test="#pass='0' or #pass='1'">
<fo:block padding-top="1cm" font-weight="bold" margin-bottom="0.2cm">Header</fo:block> <fo:block margin-top="0.2cm" margin-bottom="0.2cm" border-bottom="1px solid #e1e1e1">
</fo:block>
<fo:block margin-top="0.2cm" margin-bottom="0.2cm" padding-left="5px" padding-right="5px" padding-top="1px">
<xsl:apply-templates select="detail/katalog/frage[#ko='1' and #passed='0']" />
<xsl:apply-templates select="detail/katalog/frage/options" />
<xsl:apply-templates select="detail/katalog/matrix/frage/options" />
<xsl:apply-templates select="detail/katalog/clusterArea/clusterFrage[#ko='1' and #passed='0']" />
</fo:block>
I tried this, but it doesn't work.
<xsl:if test="(not(detail/katalog/frage[#ko='1' and #passed='0']) and not(detail/katalog/clusterArea/clusterFrage[#ko='1' and #passed='0']) and not(detail/katalog/frage/options) and not(detail/katalog/matrix/frage/options))">
<fo:block>
Not Results
</fo:block>
</xsl:if>
Thanks a lot!
PR

If the elements you are checking exist, but your current check detail/katalog/frage[#ko='1' and #passed='0'] for example will return true, as that is just checking for the existence of the element itself, regardless of whether it has child nodes or not
So, you want to do something like this....
not(detail/katalog/frage[#ko='1' and #passed='0']/text())
However, you also need to watch out for whitespace only nodes, so you might want to augment the check like so...
not(detail/katalog/frage[#ko='1' and #passed='0']/text()[normalize-space()])
Alternatively, you could strip out whitespace only nodes by using xsl:strip-space
<xsl:strip-space elements="*" />

Related

Xamarin Forms - Html2Xaml converter issue with span TapGestureRecognizer command

I'm trying to convert custom html text in FormattedString xaml for any label. There, I have an <a/> tag where it will convert to an span with TapGestureRecognizer:
<xsl:template match="A | a" priority="9">
<Span TextDecorations="Underline">
<xsl:attribute name="Text">
<xsl:apply-templates />
</xsl:attribute>
<Span.GestureRecognizers>
<TapGestureRecognizer Command="{{Binding PopupContentCommand}}">
<xsl:attribute name="CommandParameter">
<xsl:value-of select="#href" />
</xsl:attribute>
</TapGestureRecognizer>
</Span.GestureRecognizers>
</Span>
</xsl:template>
The converter is working well, the issue is that this command binding is not raising. When we load new FormattedString().LoadFromXaml(xaml) the converted html to xaml, the command appears to have binding:
But this binding is not raising. After that I try to Clear the GestureRecognizers and create an new TapGestureRecognizer adding it again. But this didn't work neither. The BindingContext appears to be the correct one too.
This is done by binding an attached property:
<Label attachedProperties:Properties.Html="{Binding HtmlText}" />
Finally it was a simulator issue. Because in the real devices this raise without problem.

Fitting the content to a single page in PDF

I am using xslt and fo to build a PDF. My requirement is to have the content of the PDF restricted to only one page.
Is some cases the PDF is coming in two pages. I have to avoid that. Below is the code for master set up.
<fo:layout-master-set>
<fo:simple-page-master master-name="StandardPage" page-height="250mm" page-width="297mm">
<fo:region-body margin-bottom="20mm" margin-top="12mm" margin-left="14mm" margin-right="6mm"/>
<fo:region-before region-name="headerContent" extent="12mm"/>
<fo:region-after region-name="footer" extent="20mm" precedence="true"/>
<fo:region-start region-name="leftBorder" extent="14mm"/>
<fo:region-end region-name="rightBorder" extent="6mm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="StandardPage">
<fo:flow flow-name="xsl-region-body">
Below is the content in the xsl. We have 18 options and the same is repeated 18 times.
<fo:table-row>
<fo:table-cell number-columns-spanned="2">
<fo:block font-size="18pt" font-family="ABC" font-weight="bold" text-align="left" line-height="14pt">
<fo:list-block>
<fo:list-item>
<fo:list-item-label>
<fo:block>•</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="4mm">
<fo:block>
<xsl:variable name="opt18" select="string(//void[#property='optionListEntryEighteen']/string/text())"/>
<xsl:value-of select="$opt18"/>
</fo:block>
</fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:block>
</fo:table-cell>
Some times all the 18 options fit to a single page and some times 16 options fit to a single page and the next two options are being moved to the next page.
My requirement is to fit the options in a single page(If 10 options are being fit in a single page then show the 10 in that single page and don't show the other options.
How can I achieve this?
I'm not confident but how about using fo:single-page-master-reference & fo:block-container with #height and #overflow="hidden"? This is tested via FOP.
[Sample FO file]
<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="simple-page-master" page-width="10.5in" page-height="5.5in">
<fo:region-body margin-top="0.5in" margin-bottom="0.5in" margin-left="0.5in"
margin-right="0.5in"/>
<fo:region-before extent="1in" precedence="true" display-align="after"/>
<fo:region-start extent="1in"/>
<fo:region-end extent="1in"/>
</fo:simple-page-master>
<fo:page-sequence-master master-name="single-page-master">
<fo:single-page-master-reference master-reference="simple-page-master"/>
</fo:page-sequence-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="single-page-master" reference-orientation="from-page-master-region()"
writing-mode="from-page-master-region()" >
<fo:flow flow-name="xsl-region-body" font-size="2em">
<fo:block-container height="4in" overflow="hidden" border="thin solid black">
<fo:block>optionListEntry (1)</fo:block>
<fo:block>optionListEntry (2)</fo:block>
<fo:block>optionListEntry (3)</fo:block>
<fo:block>optionListEntry (4)</fo:block>
<fo:block>optionListEntry (5)</fo:block>
<fo:block>optionListEntry (6)</fo:block>
<fo:block>optionListEntry (7)</fo:block>
<fo:block>optionListEntry (8)</fo:block>
<fo:block>optionListEntry (9)</fo:block>
<fo:block>optionListEntry (10)</fo:block>
<fo:block>optionListEntry (11)</fo:block>
<fo:block>optionListEntry (12)</fo:block>
<fo:block>optionListEntry (13)</fo:block>
<fo:block>optionListEntry (14)</fo:block>
<fo:block>optionListEntry (15)</fo:block>
<fo:block>optionListEntry (16)</fo:block>
<fo:block>optionListEntry (17)</fo:block>
<fo:block>optionListEntry (18)</fo:block>
</fo:block-container>
</fo:flow>
</fo:page-sequence>
</fo:root>
[The result]

XSL - Sum of computed amounts with comparison

I need some help to compute sum and add some comparison complexity to know which element should be part of the sum.
Let's take the following XML
<REF>
<amount>3</amount>
<rate>7</rate>
</REF>
<A>
<amount>10</amount>
<rate>4</rate>
</A>
<A>
<amount>-21</amount>
<rate>2</rate>
</A>
<B>
<amount>8</amount>
<rate>1</rate>
</B>
<C>
<amount>7</amount>
<rate>32</rate>
</C>
I would like to display the sum of each amount multiplied by each associated rate within a Total element.
And I would like to split my total into two elements: NegativeTotal and PositiveTotal.
PostiveTotal will contain the SUM of ((amount * rate) if the value is greater than (amount * rate) of REF object)
NegativeTotal will contain the SUM of ((amount * rate) if the value is less than (amount * rate) of REF object)
It should give the below output
<Total>
<PositiveTotal>
264 <!-- 40 + 224 -->
</PositiveTotal>
<NegativeTotal>
-34 <!-- -42 + 8 -->
</NegativeTotal>
</Total>
Please let me know if it's possible
For information technical limitation: XSLT 1.0
Thanks in advance
Regards,
I would suggest you do it this way:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/root">
<!-- first pass -->
<xsl:variable name="summands-rtf">
<xsl:for-each select="*">
<value>
<xsl:value-of select="amount * rate" />
</value>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="summands" select="exsl:node-set($summands-rtf)/value" />
<!-- get the threshold -->
<xsl:variable name="threshold" select="REF/amount * REF/rate" />
<!-- output -->
<Total>
<PositiveTotal>
<xsl:value-of select="sum($summands[. > $threshold])" />
</PositiveTotal>
<NegativeTotal>
<xsl:value-of select="sum($summands[. < $threshold])" />
</NegativeTotal>
</Total>
</xsl:template>
</xsl:stylesheet>
When applied to a well-formed XML input (with a single root element):
XML
<root>
<REF>
<amount>3</amount>
<rate>7</rate>
</REF>
<A>
<amount>10</amount>
<rate>4</rate>
</A>
<A>
<amount>-21</amount>
<rate>2</rate>
</A>
<B>
<amount>8</amount>
<rate>1</rate>
</B>
<C>
<amount>7</amount>
<rate>32</rate>
</C>
</root>
the result will be:
<?xml version="1.0" encoding="UTF-8"?>
<Total>
<PositiveTotal>264</PositiveTotal>
<NegativeTotal>-34</NegativeTotal>
</Total>
Note that the product of REF amount and rate is not included in any of the two totals, as it is neither above nor below the threshold. Similarly, if any other product happens to be equal to the threshold. it too will be excluded.

Need to parse repeatedly (loop) over the same piece of XML using NSXMLParser

I have a string of XML that I'd like to use to describe a table layout. Sort of like a template. I'm using NSXMLParser to parse this.
<section title="section a">
<row label="name" property="fullname" />
<row label="gender" property="gender" />
</section>
<section title="section b">
<row label="pet" property="pet" />
</section>
<repeat foreach="companies">
<section title="name">
<row label="address" property="address" />
<row label="email" property="email" />
</section>
</repeat>
As for the part between the <repeat> tags, I intent to loop over this part 0 to n times for each of the entries in an array. The NSXMLParser however doesn't seem to have an easy way of doing this. I see no option to jump back to a previous line. The only way I can think of is storing everything between the <repeat> tags in a variable and doing my custom parsing and repeating of it in the parser:didEndElement:... method. I wonder though, isn't there a better way to do this maybe?

Table "disappers" during XSL-FO to PDF conversion

I have the following mark-up for a table at the beginning of larger XSL-FO file:
<fo:table-and-caption xmlns:fo="http://www.w3.org/1999/XSL/Format" display-align="center">
<fo:table border="1px" border-collapse="separate" border-color="#000000" border-spacing="2px" border-style="outset" border-width="1px" role="table" text-align="center">
<fo:table-body end-indent="0pt" last-line-end-indent="0pt" role="tbody" start-indent="0pt" text-align="start" text-align-last="relative" text-indent="0pt">
<fo:table-row role="tr">
<fo:table-cell border="1px" border-style="inset" padding="1px" role="td">
<fo:block>
<fo:inline font-family="comic sans ms,sans-serif" font-size="medium" role="span">Top Left</fo:inline>
</fo:block>
</fo:table-cell>
<fo:table-cell border="1px" border-style="inset" padding="1px" role="td">
<fo:block>
<fo:inline font-family="comic sans ms,sans-serif" font-size="medium" role="span">Top Right</fo:inline>
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row role="tr">
<fo:table-cell border="1px" border-style="inset" padding="1px" role="td">
<fo:block>
<fo:inline font-family="comic sans ms,sans-serif" font-size="medium" role="span">Bottom Left</fo:inline>
</fo:block>
</fo:table-cell>
<fo:table-cell border="1px" border-style="inset" padding="1px" role="td">
<fo:block>
<fo:inline font-family="comic sans ms,sans-serif" font-size="medium" role="span">Bottom Right</fo:inline>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:table-and-caption>
The overall setup is described in my PDF report with embedded HTML question.
When our application transforms it to PDF using Apache POF, the table "disappears". The rest of the file seems to be normally converted.
Is there anything wrong with the above code?
See http://xmlgraphics.apache.org/fop/compliance.html. fo:table-and-caption is not supported. That may be the cause of your problem.
Since you don't have a caption, and since it's not supported by FOP anyway, why not omit the fo:table-and-caption element?