Skip to content

Commit

Permalink
fix Model.fromXml() failure is model has no attribute value; use stax…
Browse files Browse the repository at this point in the history
… to parse xml instead of dom
  • Loading branch information
vasyalike committed Sep 16, 2015
1 parent bb50857 commit 7c748ca
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 27 deletions.
55 changes: 28 additions & 27 deletions activejdbc/src/main/java/org/javalite/activejdbc/Model.java
Expand Up @@ -30,12 +30,10 @@
import org.javalite.common.Escape;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.*;
import java.math.BigDecimal;
import java.sql.Clob;
Expand All @@ -45,6 +43,7 @@
import java.util.*;

import static org.javalite.common.Inflector.*;
import static org.javalite.common.Util.blank;
import static org.javalite.common.Util.empty;
import static org.javalite.common.Util.join;

Expand Down Expand Up @@ -798,29 +797,31 @@ public String toString() {
* @param xml xml to read model attributes from.
*/
public void fromXml(String xml) {

try{
//such dumb API!
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(xml.getBytes()));
String topTag = underscore(getClass().getSimpleName());
Element root = document.getDocumentElement();

if(!root.getTagName().equals(topTag)){
throw new InitException("top node has to match model name: " + topTag);
}
NodeList childNodes = root.getChildNodes();

Map<String, String> attributesMap = new HashMap<String, String>();
for(int i = 0; i < childNodes.getLength();i++){
Node node = childNodes.item(i);
if(node instanceof Element){
Element child = (Element) node;
attributesMap.put(child.getTagName(), child.getFirstChild().getNodeValue());//this is even dumber!
try {
XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(new ByteArrayInputStream(xml.getBytes()));
String attr = null;
String chars = null;
Map<Object, Object> res = new HashMap<Object, Object>();
while (reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_ELEMENT:
attr = reader.getLocalName();
break;
case XMLStreamConstants.CHARACTERS:
chars = reader.getText().trim();;
break;
case XMLStreamConstants.END_ELEMENT:
if (attr != null && !blank(chars)) {
res.put(attr, chars);
}
attr = chars = null;
break;
}
}
fromMap(attributesMap);
}catch(Exception e){
throw new InitException(e);
fromMap(res);
} catch (XMLStreamException e) {
throw new InitException(e);
}
}

Expand Down
Expand Up @@ -66,6 +66,23 @@ public void shouldParseAttributesFromXml() throws ParseException {
a(p.getDate("dob")).shouldBeEqual(f.parse("1962-06-13"));
}

@Test
public void shouldNotFailXmlNoValue() throws ParseException {
deleteAndPopulateTables("people");

Person p = new Person();
String xml = readResource("/person_no_val.xml");
p.fromXml(xml);
p.saveIt();
p.refresh();

SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");

a(p.get("name")).shouldBeEqual("John");
a(p.get("last_name")).shouldBeEqual("Doe");
a(p.getDate("graduation_date")).shouldBeNull();
a(p.getDate("dob")).shouldBeEqual(f.parse("1962-06-13"));
}

@Test
public void shouldIncludeChildren(){
Expand Down
7 changes: 7 additions & 0 deletions activejdbc/src/test/resources/person_no_val.xml
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<person>
<graduation_date/>
<dob>1962-06-13</dob>
<name>John</name>
<last_name>Doe</last_name>
</person>

0 comments on commit 7c748ca

Please sign in to comment.