tags:

views:

56

answers:

3

Hi

I am quite weak at XSLT so this might seem obvious. Here is some sample XML

 <term>
  <name>cholecystocolonic fistula</name> 
  <definition>blah blah</definition> 
  <reference>cholecystocolostomy</reference> 
  </term>

And here is the XSLT I wrote a while ago to process it

<xsl:template name="term">
    {
    "dictitle": "<xsl:value-of select="name" disable-output-escaping="yes" />",
    "html": "<xsl:value-of select="definition" disable-output-escaping="yes"/>",
    "reference": "<xsl:value-of select="reference" disable-output-escaping="yes"/>
}
</xsl:template>

Basically I am creating JSON from the XML.

The requirements have now changed so that now the XML can have more than one definition tag and reference tag. They can appear in any order, i.e definition, reference, reference, definition, reference.

How can I update the XSLT to accommodate this? Probably worth mentioning that because my XSLT processor is using .NET I can only use XSLT 1.0 commands.

Many thanks!

EDIT - Clarification

This is the kind of JSON I would want created, given the following example XML

 <term>
  <name>cholecystocolonic fistula</name> 
  <definition>blah blah</definition> 
  <reference>cholecystocolostomy</reference>
  <definition>XSLT is not as easy as it should be</definition>
  <reference>qui</reference> 
  </term>

{
    dictitle: "cholecystocolonic fistula",
    html: "blah blah",
    reference: "cholecystocolostomy",
    html: "XSLT is not as easy as it should be",
    reference: "qui"
}
A: 

You'll need to use the for-each element.

This will give you an array of all the reference elements:

"references": [
    <xsl:for-each select="reference">
        <xsl:if test="position() &gt; 1">,</xsl:if>
        "<xsl:value-of select="." disable-output-escaping="yes" />"
    </xsl:for-each>
]

As you can see, I added the [] for the array and used the for-each element inside. Selecting the value of . returns the content of the current node. The output will be (roughly):

"references": ["foo", "bar", "baz"]

If this JSON structure is not what you want, please let me know.

EDIT:

If you want to preserve the order, you'll have to change the JSON structure around a bit:

"refsAndDefs": [
    <xsl:for-each select="reference|definition">
        <xsl:if test="position() &gt; 1">,</xsl:if>
        "<xsl:value-of select="name()" />": "<xsl:value-of select="." disable-output-escaping="yes" />"
    </xsl:for-each>
]

And the result will be something along the lines of

"refsAndDefs": [
    {"reference": "foo"},
    {"definition": "bar"},
    {"definition": "baz"},
    {"reference": "baa"}
]

et cetera.

Matti Virkkunen
Sorry I should have clarified that in the JSON created the reference and definition tags should appear in the same order
qui
@qui: Please see my updated answer.
Matti Virkkunen
Any reason for the downvote?
Matti Virkkunen
Well I didnt do it...
qui
+3  A: 

JSON property names have to be unique, so you can't have multiple 'reference' properties in the way you've outlined.

XML doesn't have this restriction; you're allowed to have several 'reference' nodes at the same level.

http://metajack.im/2010/02/01/json-versus-xml-not-as-simple-as-you-think/

unsquared
Ah, I didnt know this, that's a bit annoying :/
qui
Marked as the answer as it has steered me away from this approach ;(
qui
A: 

Qui,

This should generate the JSON you want but unfortunately the output is not valid JSON...

    <xsl:template match="/term">
    {
            <xsl:apply-templates select="*"/>
    }
    </xsl:template>

    <xsl:template match="name">
            "dictitle": "<xsl:value-of select="." disable-output-escaping="yes" />",
    </xsl:template>
    <xsl:template match="definition">
            "html": "<xsl:value-of select="." disable-output-escaping="yes"/>",
    </xsl:template>
    <xsl:template match="reference">
            "reference": "<xsl:value-of select="." disable-output-escaping="yes"/>
    </xsl:template>
Mrs Kensington