Subject: Re: [xsl] JSON-encoding strings in XSLT 2.0 From: Wendell Piez <wapiez@xxxxxxxxxxxxxxx> Date: Wed, 20 Nov 2013 09:47:46 -0500 |
Martynas, What do you mean by 'fragile' exactly? It's true it's not very pretty; if it's fragile under maintenance that's mainly due to the string processing. This is not XSLT's strength; and it'll be better under XSLT 3.0 (as Mike showed). You could do a bit of further refactoring like so: <xsl:template name="html-json"> <xsl:for-each-group select="xhtml:div/*" group-by="true()"> <xsl:text>{ html: '</xsl:text> <xsl:value-of disable-output-escaping="yes"> <xsl:call-template name="json-escape"> <xsl:with-param name="string"> <xsl:apply-templates select="current-group()" mode="xml-to-string"/> </xsl:with-param> </xsl:call-template> </xsl:value-of> <xsl:text>' }</xsl:text> </xsl:template> Then replace your xsl:if block with a call to this template. Note: untested. You might also consider using a character map instead of disable-output-escaping, which is an optional feature in XSLT 2.0 processors. Cheers, Wendell Wendell Piez | http://www.wendellpiez.com XML | XSLT | electronic publishing Eat Your Vegetables _____oo_________o_o___ooooo____ooooooo_^ On Tue, Nov 19, 2013 at 7:42 PM, Martynas JuseviD ius <martynas@xxxxxxxxxxxx> wrote: > Michael, > > I now realised this solution was incomplete. I have to pass a piece of > XHTML as a string into a WYSIWYG editor constructor, so not only the > characters inside text nodes are significant, but also the markup > itself. For example, the quotes surrounding attributes have to be > escaped for JSON as well. I ended up with a solution involving > xml-to-string.xsl [1] and disable-output-escaping="yes": > > <script type="text/javascript"> > jQuery(function() { > jQuery('#textarea').wymeditor( > <xsl:if test="xhtml:div/*"> > <xsl:text>{ html: '</xsl:text> > <xsl:variable name="escaped-xhtml"> > <xsl:apply-templates select="xhtml:div/*" > mode="xml-to-string"/> > </xsl:variable> > <xsl:variable name="escaped-json"> > <xsl:call-template name="json-escape"> > <xsl:with-param name="string" > select="$escaped-xhtml"/> > </xsl:call-template> > </xsl:variable> > <xsl:value-of disable-output-escaping="yes" > select="$escaped-json"/> > <xsl:text>' }</xsl:text> > </xsl:if>) > }); > </script> > > <xsl:template name="json-escape"> > <xsl:param name="string" as="xs:string?"/> > <xsl:variable name="string" select="replace($string, '\\', '\\\\')"/> > <xsl:variable name="string" select="replace($string, '"', > '\\"')"/> > <xsl:variable name="string" select="replace($string, '''', '\\''')"/> > <xsl:variable name="string" select="replace($string, '	', '\\t')"/> > <xsl:variable name="string" select="replace($string, ' ', '\\n')"/> > <xsl:variable name="string" select="replace($string, ' ', '\\r')"/> > > <xsl:value-of select="$string"/> > </xsl:template> > > It works, but seems rather fragile to me. I wonder if there is a better way? > > [1] http://lenzconsulting.com/xml-to-string/ > > Martynas > graphityhq.com > > On Tue, Oct 29, 2013 at 12:46 PM, Michael Kay <mike@xxxxxxxxxxxx> wrote: >> >> On 29 Oct 2013, at 11:02, Martynas JuseviD ius <martynas@xxxxxxxxxxxx> wrote: >> >>> Thanks Michael. I was looking at http://json.org and here's what I came up with: >>> >>> <xsl:template match="text()" mode="json-identity"> >>> <xsl:value-of >>> select="replace(replace(replace(replace(replace(replace(., '\\', >>> '\\\\'), '''', '\\'''), '"', '\\"'), '	', '\\t'), >>> ' ', '\\n'), ' ', '\\r')"/> >>> </xsl:template> >>> >>> Can this be improved? >> >> Well, I'm not going to check that the list of characters to be escaped is complete, but you've got the right idea. I would code it like this for readability: >> >>> <xsl:template match="text()" mode="json-identity"> >> <xsl:variable name="v" select="."/> >> <xsl:variable name="v" select="replace($v, '\\', '\\\\')"/> >> <xsl:variable name="v" select="replace($v, '"', '\\"')"/> >> ... >> <xsl:value-of select="$v"/> >> </xsl:variable> >> >> or in 3.0 you can use the "!" operator for function chaining: >> >>> <xsl:template match="text()" mode="json-identity"> >> <xsl:value-of select="replace(., '\\', '\\\\') ! replace(., '"', '\\"') ! ....."/> >> </xsl:variable> >> >> Michael Kay >> Saxonica >> >> >> >>> <xsl:value-of >>> select="replace(replace(replace(replace(replace(replace(., '\\', >>> '\\\\'), '''', '\\'''), '"', '\\"'), '	', '\\t'), >>> ' ', '\\n'), ' ', '\\r')"/> >> </xsl:template> >> >>> >>> On Tue, Oct 29, 2013 at 10:37 AM, Michael Kay <mike@xxxxxxxxxxxx> wrote: >>>> >>>> There's no built-in function for the job, but picking out the characters = >>>> that need special treatment (e.g. replacing newline by "\n") isn't = >>>> difficult. Handling astral characters is a bit tricky because JSON = >>>> requires them to be represented as a surrogate pair, but again the logic = >>>> for that isn't really difficult. >>>> >>>> Michael Kay >>>> Saxonica >>>> >>>> On 29 Oct 2013, at 00:56, Martynas JuseviD ius <martynas@xxxxxxxxxxxx> wrote: >>>> >>>>> Hey, >>>>> >>>>> is there some way in XSLT 2.0 to encode strings for use in JSON? In my >>>>> case, the stylesheet has to encode all text nodes in a XHTML fragment >>>>> which then gets passed to WYSIWYM editor constructor. Could this be >>>>> done as identity transform? >>>>> >>>>> I had solved this problem when I used XSLT 1.0 on PHP by calling >>>>> json_encode() as extension function, but now I'm in the Java world. >>>>> http://php.net/manual/en/function.json-encode.php >>>>> >>>>> Martynas >>>>> graphityhq.com
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] JSON-encoding strings in , Martynas Jusevičius | Thread | [xsl] exclude-result-prefixes issue, Andrew Welch |
[xsl] [Announce] Video streaming of, G. Ken Holman | Date | RE: [xsl] XSLT... Good enough to ea, Michele R Combs |
Month |