Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: force-string type hinting #11

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ You can force the creation of an array by adding the `force-array` parameter to

The `force-array` attribute will not be copied to the output JSON .

You can force the creation of a string by adding the `force-string` parameter to your XML. So instead of creating a number, the following example will create a string.

<fruitId json:force-string="true" xmlns:json="http://json.org/">123</>

{fruitId: '123'}

The `force-string` attribute will not be copied to the output JSON .

### Output formats

There are four output formats in XSLTJSON, which one to use depends on your target application. If you want the most compact JSON, use the basic output. If you want to transform XML to JSON and JSON back to XML, use the [BadgerFish](http://badgerfish.ning.com/) output. If you want something in between, you could use the RabbitFish output; which is similar to the basic version, but does distinguish between elements and attributes. If you're dealing with a lot of data centric XML, you could use the highly structured Rayfish output. All four output formats ignore XML namespaces unless the `use-namespaces` parameter is set to `true()`, in which case namespaces are created according to the BadgerFish convention.
Expand Down
62 changes: 35 additions & 27 deletions conf/xml-to-json.xsl
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:json="http://json.org/">
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:json="http://json.org/">

<xsl:output indent="no" omit-xml-declaration="yes" method="text" encoding="utf-8"/>
<xsl:strip-space elements="*"/>
Expand Down Expand Up @@ -93,23 +93,23 @@
be used on the command line.
-->
<xsl:template match="/*">
<xsl:choose>
<xsl:when test="$debug">
<xsl:variable name="json-tree">
<json:object>
<xsl:copy-of select="if (not($use-rayfish)) then json:create-node(., false()) else json:create-simple-node(.)"/>
</json:object>
</xsl:variable>

<debug>
<xsl:copy-of select="$json-tree"/>
</debug>
<xsl:apply-templates select="$json-tree" mode="json"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="json:generate(.)"/>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="$debug">
<xsl:variable name="json-tree">
<json:object>
<xsl:copy-of select="if (not($use-rayfish)) then json:create-node(., false()) else json:create-simple-node(.)"/>
</json:object>
</xsl:variable>

<debug>
<xsl:copy-of select="$json-tree"/>
</debug>
<xsl:apply-templates select="$json-tree" mode="json"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="json:generate(.)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

<!--
Expand Down Expand Up @@ -176,6 +176,7 @@
<xsl:when test="$in-array">
<json:array-value>
<json:value>
<xsl:copy-of select="$node/@json:force-array" />
<xsl:copy-of select="json:create-children($node)"/>
</json:value>
</json:array-value>
Expand All @@ -184,6 +185,7 @@
<json:member>
<xsl:copy-of select="json:create-string($node)"/>
<json:value>
<xsl:copy-of select="$node/@json:force-string" />
<xsl:copy-of select="json:create-children($node)"/>
</json:value>
</json:member>
Expand All @@ -196,7 +198,7 @@
<xsl:choose>
<xsl:when test="exists($node/child::text()) and count($node/child::node()) eq 1">
<xsl:choose>
<xsl:when test="(count($node/namespace::*) gt 0 and $use-namespaces) or count($node/@*[not(../@json:force-array) or count(.|../@json:force-array)=2]) gt 0">
<xsl:when test="(count($node/namespace::*) gt 0 and $use-namespaces) or count($node/@*[(not(../@json:force-array) or count(.|../@json:force-array)=2) and (not(../@json:force-string) or count(.|../@json:force-string)=2)]) gt 0">
<json:object>
<xsl:copy-of select="json:create-namespaces($node)"/>
<xsl:copy-of select="json:create-attributes($node)"/>
Expand All @@ -218,7 +220,7 @@
<xsl:copy-of select="json:create-namespaces($node)"/>
<xsl:copy-of select="json:create-attributes($node)"/>
<json:member>
<json:name>$</json:name>
<json:name>$d</json:name>
<json:value>
<xsl:copy-of select="json:create-mixed-array($node)"/>
</json:value>
Expand Down Expand Up @@ -313,7 +315,7 @@

<xsl:function name="json:create-attributes" as="node()*">
<xsl:param name="node" as="node()"/>
<xsl:for-each select="$node/@*[not(../@json:force-array) or count(.|../@json:force-array)=2]">
<xsl:for-each select="$node/@*[(not(../@json:force-array) or count(.|../@json:force-array)=2)]">
<json:member>
<json:name><xsl:if test="$use-badgerfish or $use-rabbitfish">@</xsl:if><xsl:value-of select="if($use-namespaces) then name() else local-name()"/></json:name>
<json:value><xsl:value-of select="."/></json:value>
Expand Down Expand Up @@ -362,7 +364,7 @@
<xsl:variable name="members"><xsl:apply-templates mode="json"/></xsl:variable>
<parameter>
<xsl:text/>{<xsl:text/>
<xsl:value-of select="string-join($members/member,',')"/>
<xsl:value-of select="string-join($members/member,',')"/>
<xsl:text/>}<xsl:text/>
</parameter>
</xsl:template>
Expand Down Expand Up @@ -410,7 +412,7 @@
* The value is not a valid JSON number (i.e. '01', '+1', '1.', and '.5' are not valid JSON numbers.)
* The value does not equal the any of the following strings: 'false', 'true', 'null'.
-->
<xsl:when test="normalize-space(.) ne . or not((string(.) castable as xs:integer and not(starts-with(string(.),'+')) and not(starts-with(string(.),'0') and not(. = '0'))) or (string(.) castable as xs:decimal and not(starts-with(string(.),'+')) and not(starts-with(.,'-.')) and not(starts-with(.,'.')) and not(starts-with(.,'-0') and not(starts-with(.,'-0.'))) and not(ends-with(.,'.')) and not(starts-with(.,'0') and not(starts-with(.,'0.'))) )) and not(. = 'false') and not(. = 'true') and not(. = 'null')">
<xsl:when test="./@json:force-string eq 'true' or ((normalize-space(.) ne . or not((string(.) castable as xs:integer and not(starts-with(string(.),'+')) and not(starts-with(string(.),'0') and not(. = '0'))) or (string(.) castable as xs:decimal and not(starts-with(string(.),'+')) and not(starts-with(.,'-.')) and not(starts-with(.,'.')) and not(starts-with(.,'-0') and not(starts-with(.,'-0.'))) and not(ends-with(.,'.')) and not(starts-with(.,'0') and not(starts-with(.,'0.'))) )) and not(. = 'false') and not(. = 'true') and not(. = 'null')))">
<xsl:text/>"<xsl:value-of select="json:encode-string(.)"/>"<xsl:text/>
</xsl:when>
<xsl:otherwise>
Expand All @@ -419,7 +421,13 @@
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:text/>null<xsl:text/>
<xsl:choose>
<xsl:when test="./@json:force-array eq 'true'">
</xsl:when>
<xsl:otherwise>
<xsl:text/>null<xsl:text/>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Expand All @@ -433,7 +441,7 @@
<xsl:apply-templates mode="json"/>
</xsl:variable>
<xsl:text/>[<xsl:text/>
<xsl:value-of select="string-join($values/value,',')"/>
<xsl:value-of select="string-join($values/value[node()],',')"/>
<xsl:text/>]<xsl:text/>
</xsl:template>
</xsl:stylesheet>
30 changes: 30 additions & 0 deletions input/tests/general.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,36 @@
<param name="use-namespaces">false</param>
</params>

<test id="force-string">
<input>
<root>
<element json:force-string="true">1234</element>
</root>
</input>
<output>
<json:object>
<json:member>
<json:name/>
<json:value>
<json:object>
<json:member>
<json:name>root</json:name>
<json:value>
<json:object>
<json:member>
<json:name>element</json:name>
<json:value json:force-string="true">1234</json:value>
</json:member>
</json:object>
</json:value>
</json:member>
</json:object>
</json:value>
</json:member>
</json:object>
</output>
</test>

<test id="force-array">
<input>
<root>
Expand Down