\n"+
" \n"+
" \n"+
" \n"+
" ";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misplaced '<' at 206 [character 1 line 7]",
e.getMessage());
}
}
/**
* Malformed XML text (incomplete CDATA string) is transformed\
* into a JSONArray. Expects a JSONException.
*/
@Test
public void invalidCDATABangInTagException() {
/**
* xmlStr contains XML text which is transformed into a JSONArray.
* In this case, the XML is invalid because an element
* does not have a complete CDATA string.
*/
String xmlStr =
"\n"+
"\n"+
" \n"+
" Joe Tester\n"+
" \n"+
" \n"+
"";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Expected 'CDATA[' at 204 [character 11 line 5]",
e.getMessage());
}
}
/**
* Convert an XML document into a JSONArray, then use JSONML.toString()
* to convert it into a string. This string is then converted back into
* a JSONArray. Both JSONArrays are compared against a control to
* confirm the contents.
*/
@Test
public void toJSONArray() {
/**
* xmlStr contains XML text which is transformed into a JSONArray.
* Each element becomes a JSONArray:
* 1st entry = elementname
* 2nd entry = attributes object (if present)
* 3rd entry = content (if present)
* 4th entry = child element JSONArrays (if present)
* The result is compared against an expected JSONArray.
* The transformed JSONArray is then transformed back into a string
* which is used to create a final JSONArray, which is also compared
* against the expected JSONArray.
*/
String xmlStr =
"\n"+
"\n"+
"\n"+
"myName\n"+
">\n"+
"\n"+
"";
String expectedStr =
"[\"addresses\","+
"{\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
"\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"},"+
"[\"address\","+
"{\"attr1\":\"attrValue1\",\"attr2\":\"attrValue2\",\"attr3\":\"attrValue3\"},"+
"[\"name\", {\"nameType\":\"mine\"},\"myName\"],"+
"[\"nocontent\"],"+
"\">\""+
"]"+
"]";
JSONArray jsonArray = JSONML.toJSONArray(xmlStr);
JSONArray expectedJsonArray = new JSONArray(expectedStr);
String xmlToStr = JSONML.toString(jsonArray);
JSONArray finalJsonArray = JSONML.toJSONArray(xmlToStr);
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray);
}
/**
* Convert an XML document into a JSONObject. Use JSONML.toString() to
* convert it back into a string, and then re-convert it into a JSONObject.
* Both JSONObjects are compared against a control JSONObject to confirm
* the contents.
*
* Next convert the XML document into a JSONArray. Use JSONML.toString() to
* convert it back into a string, and then re-convert it into a JSONArray.
* Both JSONArrays are compared against a control JSONArray to confirm
* the contents.
*
* This test gives a comprehensive example of how the JSONML
* transformations work.
*/
@Test
public void toJSONObjectToJSONArray() {
/**
* xmlStr contains XML text which is transformed into a JSONObject,
* restored to XML, transformed into a JSONArray, and then restored
* to XML again. Both JSONObject and JSONArray should contain the same
* information and should produce the same XML, allowing for non-ordered
* attributes.
*
* Transformation to JSONObject:
* The elementName is stored as a string where key="tagName"
* Attributes are simply stored as key/value pairs
* If the element has either content or child elements, they are stored
* in a jsonArray with key="childNodes".
*
* Transformation to JSONArray:
* 1st entry = elementname
* 2nd entry = attributes object (if present)
* 3rd entry = content (if present)
* 4th entry = child element JSONArrays (if present)
*/
String xmlStr =
"\n"+
"\n"+
"\n"+
"Joe Tester\n"+
"\n"+
"\n"+
"true\n"+
"false\n"+
"null\n"+
"42\n"+
"-23\n"+
"-23.45\n"+
"-23x.45\n"+
"\n"+
"1\n"+
"2\n"+
"abc\n"+
"3\n"+
"4.1\n"+
"5.2\n"+
"\n"+
"\n"+
"";
String expectedJSONObjectStr =
"{"+
"\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
"\"childNodes\":["+
"{"+
"\"childNodes\":["+
"{"+
"\"childNodes\":[\"Joe Tester\"],"+
"\"nameType\":\"my name\","+
"\"tagName\":\"name\""+
"},"+
"{"+
"\"childNodes\":[\"Baker street 5\"],"+
"\"tagName\":\"street\""+
"},"+
"{"+
"\"tagName\":\"NothingHere\","+
"\"except\":\"an attribute\""+
"},"+
"{"+
"\"childNodes\":[true],"+
"\"tagName\":\"TrueValue\""+
"},"+
"{"+
"\"childNodes\":[false],"+
"\"tagName\":\"FalseValue\""+
"},"+
"{"+
"\"childNodes\":[null],"+
"\"tagName\":\"NullValue\""+
"},"+
"{"+
"\"childNodes\":[42],"+
"\"tagName\":\"PositiveValue\""+
"},"+
"{"+
"\"childNodes\":[-23],"+
"\"tagName\":\"NegativeValue\""+
"},"+
"{"+
"\"childNodes\":[-23.45],"+
"\"tagName\":\"DoubleValue\""+
"},"+
"{"+
"\"childNodes\":[\"-23x.45\"],"+
"\"tagName\":\"Nan\""+
"},"+
"{"+
"\"childNodes\":["+
"{"+
"\"childNodes\":[1],"+
"\"tagName\":\"value\""+
"},"+
"{"+
"\"childNodes\":[2],"+
"\"tagName\":\"value\""+
"},"+
"{"+
"\"childNodes\":["+
"{"+
"\"childNodes\":[\"abc\"],"+
"\"svAttr\":\"svValue\","+
"\"tagName\":\"subValue\""+
"}"+
"],"+
"\"tagName\":\"value\""+
"},"+
"{"+
"\"childNodes\":[3],"+
"\"tagName\":\"value\""+
"},"+
"{"+
"\"childNodes\":[4.1],"+
"\"tagName\":\"value\""+
"},"+
"{"+
"\"childNodes\":[5.2],"+
"\"tagName\":\"value\""+
"}"+
"],"+
"\"tagName\":\"ArrayOfNum\""+
"}"+
"],"+
"\"addrType\":\"my address\","+
"\"tagName\":\"address\""+
"}"+
"],"+
"\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\","+
"\"tagName\":\"addresses\""+
"}";
String expectedJSONArrayStr =
"["+
"\"addresses\","+
"{"+
"\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
"\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\""+
"},"+
"["+
"\"address\","+
"{"+
"\"addrType\":\"my address\""+
"},"+
"["+
"\"name\","+
"{"+
"\"nameType\":\"my name\""+
"},"+
"\"Joe Tester\""+
"],"+
"[\"street\",\"Baker street 5\"],"+
"["+
"\"NothingHere\","+
"{\"except\":\"an attribute\"}"+
"],"+
"[\"TrueValue\",true],"+
"[\"FalseValue\",false],"+
"[\"NullValue\",null],"+
"[\"PositiveValue\",42],"+
"[\"NegativeValue\",-23],"+
"[\"DoubleValue\",-23.45],"+
"[\"Nan\",\"-23x.45\"],"+
"["+
"\"ArrayOfNum\","+
"[\"value\",1],"+
"[\"value\",2],"+
"[\"value\","+
"["+
"\"subValue\","+
"{\"svAttr\":\"svValue\"},"+
"\"abc\""+
"],"+
"],"+
"[\"value\",3],"+
"[\"value\",4.1],"+
"[\"value\",5.2]"+
"]"+
"]"+
"]";
// make a JSONObject and make sure it looks as expected
JSONObject jsonObject = JSONML.toJSONObject(xmlStr);
JSONObject expectedJsonObject = new JSONObject(expectedJSONObjectStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
// restore the XML, then make another JSONObject and make sure it
// looks as expected
String jsonObjectXmlToStr = JSONML.toString(jsonObject);
JSONObject finalJsonObject = JSONML.toJSONObject(jsonObjectXmlToStr);
Util.compareActualVsExpectedJsonObjects(finalJsonObject, expectedJsonObject);
// create a JSON array from the original string and make sure it
// looks as expected
JSONArray jsonArray = JSONML.toJSONArray(xmlStr);
JSONArray expectedJsonArray = new JSONArray(expectedJSONArrayStr);
Util.compareActualVsExpectedJsonArrays(jsonArray,expectedJsonArray);
// restore the XML, then make another JSONArray and make sure it
// looks as expected
String jsonArrayXmlToStr = JSONML.toString(jsonArray);
JSONArray finalJsonArray = JSONML.toJSONArray(jsonArrayXmlToStr);
Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray);
// lastly, confirm the restored JSONObject XML and JSONArray XML look
// reasonably similar
JSONObject jsonObjectFromObject = JSONML.toJSONObject(jsonObjectXmlToStr);
JSONObject jsonObjectFromArray = JSONML.toJSONObject(jsonArrayXmlToStr);
Util.compareActualVsExpectedJsonObjects(jsonObjectFromObject, jsonObjectFromArray);
}
/**
* Convert an XML document which contains embedded comments into
* a JSONArray. Use JSONML.toString() to turn it into a string, then
* reconvert it into a JSONArray. Compare both JSONArrays to a control
* JSONArray to confirm the contents.
*
* This test shows how XML comments are handled.
*/
@Test
public void commentsInXML() {
String xmlStr =
"\n"+
"\n"+
"\n"+
"\n"+
"\n"+
"Joe Tester\n"+
"\n"+
"Baker street 5\n"+
"\n"+
"";
String expectedStr =
"[\"addresses\","+
"[\"address\","+
"[\"name\",\"Joe Tester\"],"+
"[\"street\",\"Baker street 5\"]"+
"]"+
"]";
JSONArray jsonArray = JSONML.toJSONArray(xmlStr);
JSONArray expectedJsonArray = new JSONArray(expectedStr);
String xmlToStr = JSONML.toString(jsonArray);
JSONArray finalJsonArray = JSONML.toJSONArray(xmlToStr);
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray);
}
/**
* JSON string with lost leading zero and converted "True" to true. See test
* result in comment below.
*/
@Test
public void testToJSONArray_jsonOutput() {
final String originalXml = "011000- True
";
final String expectedJsonString = "[\"root\",[\"id\",\"01\"],[\"id\",1],[\"id\",\"00\"],[\"id\",0],[\"item\",{\"id\":\"01\"}],[\"title\",true]]";
final JSONArray actualJsonOutput = JSONML.toJSONArray(originalXml, false);
assertEquals(expectedJsonString, actualJsonOutput.toString());
}
/**
* JSON string cannot be reverted to original xml when type guessing is used.
*/
@Test
public void testToJSONArray_reversibility() {
final String originalXml = "011000- True
";
final String revertedXml = JSONML.toString(JSONML.toJSONArray(originalXml, false));
assertNotEquals(revertedXml, originalXml);
}
/**
* JSON string cannot be reverted to original xml when type guessing is used.
* When we force all the values as string, the original text comes back.
*/
@Test
public void testToJSONArray_reversibility2() {
final String originalXml = "011000- True
";
final String expectedJsonString = "[\"root\",[\"id\",\"01\"],[\"id\",\"1\"],[\"id\",\"00\"],[\"id\",\"0\"],[\"item\",{\"id\":\"01\"}],[\"title\",\"True\"]]";
final JSONArray json = JSONML.toJSONArray(originalXml,true);
assertEquals(expectedJsonString, json.toString());
final String reverseXml = JSONML.toString(json);
assertEquals(originalXml, reverseXml);
}
/**
* JSON can be reverted to original xml.
*/
@Test
public void testToJSONArray_reversibility3() {
final String originalXml = "400
402
";
final JSONArray jsonArray = JSONML.toJSONArray(originalXml, false);
final String revertedXml = JSONML.toString(jsonArray);
assertEquals(revertedXml, originalXml);
}
/**
* JSON string cannot be reverted to original xml. See test result in
* comment below.
*/
@Test
public void testToJSONObject_reversibility() {
final String originalXml = "400
402
";
final JSONObject originalObject=JSONML.toJSONObject(originalXml,false);
final String originalJson = originalObject.toString();
final String xml = JSONML.toString(originalObject);
final JSONObject revertedObject = JSONML.toJSONObject(xml, false);
final String newJson = revertedObject.toString();
assertTrue("JSON Objects are not similar",originalObject.similar(revertedObject));
assertEquals("original JSON does not equal the new JSON",originalJson, newJson);
}
// these tests do not pass for the following reasons:
// 1. Our XML parser does not handle generic HTML entities, only valid XML entities. Hence
// or other HTML specific entities would fail on reversability
// 2. Our JSON implementation for storing the XML attributes uses the standard unordered map.
// This means that can not be reversed reliably.
//
// /**
// * Test texts taken from jsonml.org. Currently our implementation FAILS this conversion but shouldn't.
// * Technically JsonML should be able to transform any valid xhtml document, but ours only supports
// * standard XML entities, not HTML entities.
// */
// @Test
// public void testAttributeConversionReversabilityHTML() {
// final String originalXml = "
#5D28D1 | Example text here |
#AF44EF | 127310656 |
#AAD034 | © |
";
// final String expectedJsonString = "[\"table\",{\"class\" : \"MyTable\",\"style\" : \"background-color:yellow\"},[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#550758\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:red\"},\"Example text here\"]],[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#993101\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:green\"},\"127624015\"]],[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#E33D87\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:blue\"},\"\u00A0\",[\"span\",{ \"style\" : \"background-color:maroon\" },\"\u00A9\"],\"\u00A0\"]]]";
// final JSONArray json = JSONML.toJSONArray(originalXml,true);
// final String actualJsonString = json.toString();
//
// final String reverseXml = JSONML.toString(json);
// assertNotEquals(originalXml, reverseXml);
//
// assertNotEquals(expectedJsonString, actualJsonString);
// }
//
// /**
// * Test texts taken from jsonml.org but modified to have XML entities only.
// */
// @Test
// public void testAttributeConversionReversabilityXML() {
// final String originalXml = "#5D28D1 | Example text here |
#AF44EF | 127310656 |
#AAD034 | &>< |
";
// final String expectedJsonString = "[\"table\",{\"class\" : \"MyTable\",\"style\" : \"background-color:yellow\"},[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#550758\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:red\"},\"Example text here\"]],[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#993101\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:green\"},\"127624015\"]],[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#E33D87\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:blue\"},\"&\",[\"span\",{ \"style\" : \"background-color:maroon\" },\">\"],\"<\"]]]";
// final JSONArray jsonML = JSONML.toJSONArray(originalXml,true);
// final String actualJsonString = jsonML.toString();
//
// final String reverseXml = JSONML.toString(jsonML);
// // currently not equal because the hashing of the attribute objects makes the attribute
// // order not happen the same way twice
// assertEquals(originalXml, reverseXml);
//
// assertEquals(expectedJsonString, actualJsonString);
// }
}