Open GoogleCodeExporter opened 9 years ago
Some XSLT processors throw an error on your match pattern:
"The current() function may not be used in a match pattern."
To get around this error, I had to combine the "object" and "array" templates
into 1
new template that can handle both. I used your same pattern to check for an
array,
but it is located in an <xsl:when>'s test expression, instead, which avoids the
error.
<!-- objects and arrays -->
<xsl:template match="*" name="base">
<xsl:if test="not(preceding-sibling::*)">{</xsl:if>
<xsl:choose>
<!-- array -->
<xsl:when test="count(../*[name(current())=name()])>1">
<xsl:variable name="el" select="name()"/>
<xsl:if test="not(following-sibling::*[name()=$el])">
<xsl:call-template name="escape-string">
<xsl:with-param name="s" select="$el"/>
</xsl:call-template>
<xsl:text>:[</xsl:text>
<xsl:for-each select="../*[name()=$el]">
<xsl:if test="position()!=1">,</xsl:if>
<xsl:choose>
<xsl:when test="not(child::node())">
<xsl:text>null</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="child::node()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:text>]</xsl:text>
<xsl:if test="following-sibling::*">,</xsl:if>
</xsl:if>
</xsl:when>
<!-- object -->
<xsl:otherwise>
<xsl:call-template name="escape-string">
<xsl:with-param name="s" select="name()"/>
</xsl:call-template>
<xsl:text>:</xsl:text>
<!-- check type of node -->
<xsl:choose>
<!-- null nodes -->
<xsl:when test="count(child::node())=0">null</xsl:when>
<!-- other nodes -->
<xsl:otherwise>
<xsl:apply-templates select="child::node()"/>
</xsl:otherwise>
</xsl:choose>
<!-- end of type check -->
<xsl:if test="following-sibling::*">,</xsl:if>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="not(following-sibling::*)">}</xsl:if>
</xsl:template>
I've attached my changes in the full XSLT file.
Original comment by Jason.Mo...@gmail.com
on 26 Feb 2008 at 5:55
Attachments:
How does this deal with single children? Does it make them an array or an
object and can you override it?
See issue 6 for the array case.
Original comment by docw...@gmail.com
on 27 Mar 2008 at 5:35
I'm not sure this is a bug. The spec. say that it'll only be an array if all
the siblings have the same name().
Otherwise, I think it is too confusing.
I'll think about it for a while. Maybe one of the other developers can chime
in.
Original comment by docw...@gmail.com
on 31 Mar 2008 at 4:46
Whups! I get it. You can't have "test": twice. Hmm....
More interesting case:
<root>
<item>1</item>
<name>Georg</name>
<item>2</item>
</root>
Should these just throw an error of some kind or actually work right?
Ciao!
Original comment by docw...@gmail.com
on 31 Mar 2008 at 5:23
Anthony:
On the comments, you expressed interest in handling this one. Should I just leave this to you?
Original comment by docw...@gmail.com
on 31 Mar 2008 at 5:25
I have an initial solution for this I've used in my application, just needs
some more
testing to make sure it doesn't work only for my case. Yes, I can accept it. I
think my solution parallels the ones that I see in the comments - hopefully I
will
have some time to tackle this later this week.
Original comment by anthony....@gmail.com
on 31 Mar 2008 at 7:26
I've at last had a chance to tackle this and I've mostly cleaned up my
solution.
Before I check it in I want to do testing, because I am not convinced what I was
working on is really that different from what was already proposed.
A few quick questions:
- The expected output of
<root><item>1</item><item>2</item><name>test</name></root>
should be:
{"root":{"item":[1,2],"name":"test"}}
correct?
- To Jason: what XSLT processors fail on Wayne's script? I'm trying to compare
your
solution to my solution to see which one will be more robust. What I was doing
seems
like it might suffer the same current() problem you found in Wayne's file, so I
want
to replicate this.
I've inlined the diff stanzas below, and attached the current version of the
file.
<!-- item:null -->
<xsl:template match="*[count(child::node())=0]">
<xsl:call-template name="escape-string">
<xsl:with-param name="s" select="local-name()"/>
</xsl:call-template>
<xsl:text>:null</xsl:text>
<xsl:choose>
<xsl:when test="following-sibling::*">,</xsl:when>
<xsl:otherwise>}</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- object -->
<xsl:template match="*" name="base">
<xsl:if test="not(preceding-sibling::*)">{</xsl:if>
<xsl:call-template name="escape-string">
<xsl:with-param name="s" select="name()"/>
</xsl:call-template>
<xsl:text>:</xsl:text>
<!-- check type of node -->
<xsl:apply-templates select="child::node()"/>
<!-- end of type check -->
<xsl:choose>
<xsl:when test="following-sibling::*">,</xsl:when>
<xsl:otherwise>}</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- partial array: children without repeated names need to be shown as singletons -->
<xsl:template match="*[count(../*[name()=name(current())])<count(../*) and
count(../*[name()=name(current())])>1]">
<xsl:if test="not(preceding-sibling::*)">{</xsl:if>
<xsl:call-template name="escape-string">
<xsl:with-param name="s" select="name()"/>
</xsl:call-template>
<xsl:text>: </xsl:text>
<xsl:apply-templates select="child::node()"/>
<xsl:if test="following-sibling::*">,</xsl:if>
<xsl:if test="not(following-sibling::*)">}</xsl:if>
</xsl:template>
<!-- partial array: children with repeated names need to be grouped in an array -->
<xsl:template match="*[count(../*[name()=name(current())])>1]">
<xsl:if test="not(preceding-sibling::*)">{</xsl:if>
<xsl:if test="not(preceding-sibling::*[name()=name(current())])">
<xsl:call-template name="escape-string">
<xsl:with-param name="s" select="name()"/>
</xsl:call-template>
<xsl:text>:[</xsl:text></xsl:if>
<xsl:choose>
<xsl:when test="not(child::node())">
<xsl:text>null</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="child::node()"/>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="following-sibling::*[name()=name(current())]">,</xsl:if>
<xsl:if test="not(following-sibling::*[name()=name(current())])">
<xsl:if test="following-sibling::*">],</xsl:if>
<xsl:if test="not(following-sibling::*)">]}</xsl:if>
</xsl:if>
</xsl:template>
<!-- array -->
<xsl:template match="*[count(../*[name(../*)=name(.)])=count(../*) and
count(../*)>1]">
<xsl:if test="not(preceding-sibling::*)">[</xsl:if>
<xsl:choose>
<xsl:when test="not(child::node())">
<xsl:text>null</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="child::node()"/>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="following-sibling::*">,</xsl:if>
<xsl:if test="not(following-sibling::*)">]</xsl:if>
</xsl:template>
Original comment by anthony....@gmail.com
on 1 May 2008 at 10:01
Attachments:
Waiting to hear back from various people before checking anything in. In the
meantime, attached is the script I've been using to run the unit tests, and the
new/changed files in the test data.
Original comment by anthony....@gmail.com
on 1 May 2008 at 10:04
Attachments:
I have "java.lang.RuntimeException: XSLT TransformerFactory Error" trying to
apply
transformation from last Antony's message as well as first wayneburkett's
stylesheet.
Jason's solution seems to be working fine. I believe you can reproduce the
error -
just try to make transformation using standard java transformer (
javax.xml.transform ).
Original comment by ase...@gmail.com
on 4 May 2008 at 11:27
Aserba,
Thank you! Sorry for the late reply, I started a new project May 5th and it's
eating
a lot of my time.
I will try to replicate your error and will make corrections. Maybe it would be
better to try to make Jason's solution pass the unit tests rather than to fix my
solution. I will find out and let you know.
-Anthony
Original comment by anthony....@gmail.com
on 9 May 2008 at 9:33
Ok, I was able to replicate that error in a slightly different way. To fix the
problem, I have taken Jason's XSLT sheets for JSON, modified them so that all
the
unit tests pass, and replicated the changes into the JS XSLT. His code was
pretty
easy to work with and fairly easy to port back to the Javascript.
In initial testing, I no longer get the same errors. I am not directly testing
using
javax.xml.transform, though, which I will try next. In the meantime, here are
the
initial versions of these files. Please check them out and let me know if this
looks
like it is going in the right direction.
Original comment by anthony....@gmail.com
on 31 May 2008 at 12:59
Attachments:
Anthony,
"The expected output of
<root><item>1</item><item>2</item><name>test</name></root>
should be:
{"root":{"item":[1,2],"name":"test"}}
correct?"
Why not just {"item":[1,2],"name":"test"}. The root node should be absorbed.
/Jakob
Original comment by kr...@kruse-net.dk
on 2 Jun 2008 at 9:02
Ok, I will take a look at that and see if I can make that happen. I didn't
realize
that requirement in the convention to absorb the root node would interact with
this
change - in my own code the arrays are usually deeply embedded so it never came
up.
Original comment by anthony....@gmail.com
on 3 Jun 2008 at 5:26
Anthony, could you possibly put the latest versions of the XSLT's that fix this
issue in the repository, in a branch maybe?
Original comment by emyr.tho...@gmail.com
on 3 Sep 2010 at 2:17
newbee!
I have the following issue:
A section of my XML looks like this:
<RatingDetails>
<RatingDetail>
<Semantic>Communication Ability</Semantic>
<Rating>5</Rating>
</RatingDetail>
<RatingDetail>
<Semantic>Responsiveness</Semantic>
<Rating>5</Rating>
</RatingDetail>
<RatingDetail>
<Semantic>Quality of Service</Semantic>
<Rating>5</Rating>
</RatingDetail>
<RatingDetail>
<Semantic>Value for Money</Semantic>
<Rating>5</Rating>
</RatingDetail>
</RatingDetails>
But after applying the stylesheet - I get this:
"RatingDetails":[{"Semantic":"Communication
Ability","Rating":5},{"Semantic":"Responsiveness","Rating":5},{"Semantic":"Quali
ty of Service","Rating":5},{"Semantic":"Value for Money","Rating":5}]
What happened to the "RatingDetail" node? (without the 's')
Original comment by maxh...@gmail.com
on 8 Jun 2011 at 1:57
I just to learn it,could you give me some example about how to call it? thank
you very much
Original comment by chengdou...@gmail.com
on 2 Jul 2013 at 9:10
Guys, you forgot about skip hint!
Original comment by dms.pop3...@gmail.com
on 22 Apr 2014 at 12:19
we faced the same issue as reported above
Here is the updated output for user input
{"RatingDetails":{"RatingDetail":[{"Semantic":"Communication
Ability","Rating":5},{"Semantic":"Responsiveness","Rating":5},{"Semantic":"Quali
ty of Service","Rating":5},{"Semantic":"Value for Money","Rating":5}]}}
also attaching the updated xsl.
Please update if it passes your tests.
Original comment by findsand...@gmail.com
on 25 Jul 2014 at 6:38
Attachments:
Original issue reported on code.google.com by
waynebur...@gmail.com
on 29 Dec 2007 at 1:57Attachments: