Question

I've seen similar, but not quite questions as this, but here is what I'm trying to do. I have the XML from my SMS, and from it, create a PDF log. Works great. Tried to add this new element, and I've gotten the "replace" function in XSLT working to replace characters, but I want to instead, put in an external graphic, using a variable. If I paste the contents of my XSLT variable directly into the FO doc, it produces the PDF with no issue, but I'm not getting my tag and contents over to the FO file. I'm guessing that I'm missing something simple.

XML snippet:

<?xml version="1.0" encoding="UTF-8"?>
<SMSExport>
    <SMSMessage>
        <Kind>Sent</Kind>
        <DateTime>2011-11-08 12:14:23 -0800</DateTime>
        <Name>Sendee's name</Name>
        <Number>+15553009008</Number>
        <Message>Yay!!!  - </Message>
    </SMSMessage>
</SMSExport>

XML snippet:

<xsl:if test="not(following-sibling::Message/@File)">
    <!-- Needs rework!!!  "Graphic not taking -->
    <xsl:variable name="emoji">
        <fo:external-graphic src="emoji/emoji-E057.png"
            content-height=".15in"/>
    </xsl:variable>
        <!-- Repeat added, to show a string replace works -->
    <xsl:value-of select="replace(following-sibling::Message, '', ';-)')"/>
        <fo:block/>
    <xsl:value-of select="replace(following-sibling::Message, '',$emoji)"/>
</xsl:if>

Gives the resulting FO block snippet of:

<fo:block start-indent=".35in" end-indent=".25in" keep-with-next="always">
    Yay!!! ;-) - ;-);-);-)
        <fo:block/>
    Yay!!!  -
</fo:block>

Thanks in advance!

ADDITION: (using LarsH's answer, here is how I handled recursion. Hope it might help someone else.

To work on a string recursively, I kept pasting in the block above, with a new regex. This was putting separate instances of the analysis, and so I kept getting the line repeated, with each new item replaced. That is, with three blocks, searching for three items (X, Y, Z):

This is the result of (x.gif)YZ.
This is the result of X(y.gif)Z.
This is the result of XY(z.gif).

Instead of what I wanted, which was:

This is the result of (x.gif)(y.gif)(z.gif).

For others, to handle this, simply replace the non-matching

<xsl:copy-of select="."/>

line, with a nesting of the next analyze block (I've also substituted the emoji character, with it's hex value, to avoid the empty boxes, in this example). I've only done it for two items/levels here, but you would just continue the nesting, and it works great:

<xsl:analyze-string select="following-sibling::Message" regex="&#xE057;">
    <xsl:matching-substring>
        <xsl:copy-of select="$E057"/>
    </xsl:matching-substring>
    <xsl:non-matching-substring>
        <xsl:analyze-string select="." regex="&#xE120">
            <xsl:matching-substring>
                <xsl:copy-of select="$E120"/>
            </xsl:matching-substring>
            <xsl:non-matching-substring>
                <xsl:copy-of select="."/>
            </xsl:non-matching-substring>
        </xsl:analyze-string>
     </xsl:non-matching-substring>
</xsl:analyze-string>
Was it helpful?

Solution

The replace() function replaces occurences of a pattern with a string. The string value of $emoji is the concatenation of its text nodes -- namely, the empty string. In other words, replace() cannot do what you need.

The question boils down to, how do I replace a character (or pattern) in a string with an XML fragment?

A good solution is to use xsl:analyze-string to replace occurrences of your pattern, '', with the full structured content of $emoji:

<xsl:analyze-string select="following-sibling::Message" regex="">
  <xsl:matching-substring>
    <xsl:copy-of select="$emoji" />
  </xsl:matching-substring>
  <xsl:non-matching-substring>
    <xsl:value-of select="."/>
  </xsl:non-matching-substring>
</xsl:analyze-string>

instead of using <xsl:value-of>, which can only output text.

OTHER TIPS

If you are using XSLT 2.0, character maps provide a simpler way to do what you want. The relevant section of the XSLT 2.0 spec has an example which includes supplying HTML img elements for particular characters.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top