2013-03-16 86 views
0

我试图建立一种可靠且快速的方式将XML转换为使用Java的JSON,并且我已经开始使用XStream来执行此任务。但是,当我在下面运行代码时由于空白(包括换行符)而导致测试失败,如果我删除这些字符,则测试会通过。在使用XStream将XML转换为JSON时忽略空白

@Test 
    public void testXmlWithWhitespaceBeforeStartElementCanBeConverted() throws Exception { 
     String xml = 
       "<root>\n" + 
       " <foo>bar</foo>\n" + // remove the newlines and white space to make the test pass 
       "</root>"; 
     String expectedJson = "{\"root\": {\n" + 
       " \"foo\": bar\n" + 
       "}}"; 
     String actualJSON = transformXmlToJson(xml); 

     Assert.assertEquals(expectedJson, actualJSON); 
    } 

    private String transformXmlToJson(String xml) throws XmlPullParserException { 
     XmlPullParser parser = XppFactory.createDefaultParser(); 
     HierarchicalStreamReader reader = new XppReader(new StringReader(xml), parser, new NoNameCoder()); 
     StringWriter write = new StringWriter(); 
     JsonWriter jsonWriter = new JsonWriter(write); 
     HierarchicalStreamCopier copier = new HierarchicalStreamCopier(); 
     copier.copy(reader, jsonWriter); 
     jsonWriter.close(); 
     return write.toString(); 
    } 

测试失败例外:

com.thoughtworks.xstream.io.json.AbstractJsonWriter$IllegalWriterStateException: Cannot turn from state SET_VALUE into state START_OBJECT for property foo 
    at com.thoughtworks.xstream.io.json.AbstractJsonWriter.handleCheckedStateTransition(AbstractJsonWriter.java:265) 
    at com.thoughtworks.xstream.io.json.AbstractJsonWriter.startNode(AbstractJsonWriter.java:227) 
    at com.thoughtworks.xstream.io.json.AbstractJsonWriter.startNode(AbstractJsonWriter.java:232) 
    at com.thoughtworks.xstream.io.copy.HierarchicalStreamCopier.copy(HierarchicalStreamCopier.java:36) 
    at com.thoughtworks.xstream.io.copy.HierarchicalStreamCopier.copy(HierarchicalStreamCopier.java:47) 
    at testConvertXmlToJSON.transformXmlToJson(testConvertXmlToJSON.java:30) 

有没有办法来告诉复制过程中忽略忽略的空白。我找不到任何明显的方法来实现这一行为,但我认为它应该在那里。我知道我可以预先处理XML以删除空白区域,或者也许只是使用另一个库。

更新 我可以解决此问题使用HierarchicalStreamReader接口的装饰以及手工压制的空白点,这仍然不觉得理想虽然。这看起来像下面的代码,这将使测试通过。

public class IgnoreWhitespaceHierarchicalStreamReader implements HierarchicalStreamReader { 
     private HierarchicalStreamReader innerHierarchicalStreamReader; 

     public IgnoreWhitespaceHierarchicalStreamReader(HierarchicalStreamReader hierarchicalStreamReader) { 
      this.innerHierarchicalStreamReader = hierarchicalStreamReader; 
     } 

     public String getValue() { 
      String getValue = innerHierarchicalStreamReader.getValue(); 
      System.out.printf("getValue = '%s'\n", getValue); 
      if(innerHierarchicalStreamReader.hasMoreChildren() && getValue.length() >0)   { 
       if(getValue.matches("^\\s+$")) { 
        System.out.printf("*** White space value suppressed\n"); 
        getValue = ""; 
       } 
      } 
      return getValue; 
     } 
     // rest of interface ... 

任何帮助表示赞赏。

回答

0

比较两个XML作为String对象不是一个好主意。如果xml相同,但节点的顺序不同,你将如何处理大小写。

例如

<xml><node1>1</node1><node2>2</node2></xml> 

类似于

<xml><node2>2</node2><node1>1</node1></xml> 

但是当你做一个字符串比较它将始终返回false。

改为使用像XMLUnit这样的工具。请参考以下链接查看更多细节,

Best way to compare 2 XML documents in Java

+0

感谢您的答复,但我没有看到我的表演XML的比较。你是指在删除空白处的decarator内吗? – Darren 2013-03-28 10:28:30

+0

我的意思是当你调用Assert.assertEquals时。这两个参数都是String对象,因此将调用String.equals()方法。相反,您将不得不创建XMLObject类来重写它的equals方法来执行XML比较。 – ABose 2013-04-03 08:06:59

+0

assertEquals正在测试JSON字符串而不是XML字符串。我同意,如果JSON字符串的内容可能不准确,因此测试可能因此失败(但我没有那么远),我应该测试等价性。测试只是为了简洁而显示,并不是引发异常的原因。 – Darren 2013-04-04 05:18:31