Не парсер XML с помощью библиотеки SimpleXML
У меня есть проблема, когда я пытаюсь вставить строку xml в объект с помощью библиотеки SimpleXML(версия 2.7.1).
Это моя строка:
<tbody>
<tr>
<th></th>
<th>Weather</th>
<th><img src="http://localhost:8080/img/today" /></th>
<th><img src="http://localhost:8080/img/today_1" /></th>
<th><img src="http://localhost:8080/img/today_2" /></th>
</tr>
<tr>
<td><img src="http://localhost:8080/img/location_1" /></td>
<td> <a href="/Ney-tag/" title="Ney" target="_blank" style="color:#7A2200;">Ney</a> </td>
<td> 14 </td>
<td> 15 </td>
<td> 16 </td>
</tr>
<tr>
<td><img src="http://localhost:8080/img/location_2" /></td>
<td> <a href="/Pana-tag/" title="Pana" target="_blank" style="color:#7A2200;">Pana</a> </td>
<td> 30 </td>
<td> 31 </td>
<td> 30 </td>
</tr>
<tr>
<td><img src="http://localhost:8080/img/location_3" /></td>
<td> <a href="/Sin-tag/" title="Sin" target="_blank" style="color:red;font-weight:bold;">Sin</a> </td>
<td> 32 </td>
<td> 33 </td>
<td> 36 </td>
</tr>
</tbody>
И вот моя модель:
@Root
public class TBody {
@ElementList
List<TR> tr;
}
public class TR {
@ElementList(entry = "th")
List<TH> th;
@ElementList(entry = "td")
List<TD> td;
public TR() {
}
public static class TH {
@Element
String th;
@Element
IMG img;
public TH() {
// TODO Auto-generated constructor stub
}
}
public static class IMG{
@Element
String img;
@Attribute
String src;
public IMG() {
}
}
public static class TD {
@Element
IMG img;
@Element
String td;
@Element
A a;
}
public static class A{
@Element
String a;
@Attribute
String href;
@Attribute
String title;
@Attribute
String target;
@Attribute
String style;
public A() {
}
}
}
Это трассировка logcat:
05-12 23:14:46.711 W/System.err﹕ org.simpleframework.xml.core.ValueRequiredException:
Unable to satisfy @org.simpleframework.xml.ElementList(data=false, empty=true, entry=td, inline=false, name=, required=true, type=void) on field 'td' java.util.List
com.example.model.TR.td for class com.example..model.TR at line 3
05-12 23:14:46.711 W/System.err﹕ at org.simpleframework.xml.core.Composite.validate(Composite.java:644)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Composite.readElements(Composite.java:449)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Composite.access$400(Composite.java:59)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Composite$Builder.read(Composite.java:1383)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Composite.read(Composite.java:201)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Composite.read(Composite.java:148)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Traverser.read(Traverser.java:92)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.CompositeList.populate(CompositeList.java:175)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.CompositeList.read(CompositeList.java:120)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Composite.readVariable(Composite.java:623)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Composite.readInstance(Composite.java:573)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Composite.readUnion(Composite.java:549)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Composite.readElement(Composite.java:532)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Composite.readElements(Composite.java:445)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Composite.access$400(Composite.java:59)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Composite$Builder.read(Composite.java:1383)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Composite.read(Composite.java:201)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Composite.read(Composite.java:148)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Traverser.read(Traverser.java:92)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Persister.read(Persister.java:625)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Persister.read(Persister.java:606)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Persister.read(Persister.java:584)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Persister.read(Persister.java:562)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Persister.read(Persister.java:499)
05-12 23:14:46.715 W/System.err﹕ at org.simpleframework.xml.core.Persister.read(Persister.java:408)
Может ли кто-нибудь помочь мне понять причину здесь ?
Спасибо!
1 ответ:
[удалено, потому что в нем были ошибки]
- добавлены
@Root
аннотации ко всем классам- добавлено
inline=true
ко всем спискам элементов- добавлены
type = _.class
к спискам элементов- добавлено
required=false
дляth
иtd
- добавлены явные пустые конструкторы
EDIT: пришлось добавить некоторые
required=false
, но что более важно,SimpleXML
не может обрабатывать как@Text
, так и@Element
теги на одном и том же объекте данных, поэтому я использовал решение в этом вопросе , чтобы изменить XML в чтобы обеспечить фактическое@Element
, а не@Text
.Мое окончательное решение, которое разбирает правильно, следующее:
@Root public class A{ @Element(required=false) String a; @Attribute String href; @Attribute String title; @Attribute String target; @Attribute(required=false) String style; public A() { } } @Root public class IMG { @Element(required=false) String img; @Attribute String src; public IMG() { } } @Root(name="tbody") public class TBody { @ElementList(entry = "tr", inline=true, type=TR.class) List<TR> tr; public TBody() {} } @Root public class TD { @Element(required=false) IMG img; @Element(required=false) Content content; @Element(required=false) A a; public TD() {} } @Root public class TH { @Element(data=true, required=false) Content content; @Element(name="img", required=false) IMG img; public TH() { // TODO Auto-generated constructor stub } } @Root public class TR { @ElementList(entry = "th", inline = true, type = TH.class, required = false) List<TH> th; @ElementList(entry = "td", inline = true, type = TD.class, required = false) List<TD> td; public TR() { } }
Также добавлен класс:
@Root public class Content { @Text(required=false) String content; }
И мне пришлось использовать следующее
Persister
, аналогично тому, что было в связанном вопросе:public class SerializerWithPreprocessor extends Persister { public SerializerWithPreprocessor() { } @Override public <T> T read(Class<? extends T> type, String source) throws Exception { //System.out.println("Source: " + source); source = source.replaceAll("<th>([[\\s||\\w||[+=]]&&[^<>]]+)</th>", "<th><content>$1</content></th>"); source = source.replaceAll("<td>([[\\s||\\d||\\w||[+=]]&&[^<>]]+)</td>", "<td><content>$1</content></td>"); //System.out.println("Source2: " + source); return super.read(type, source); } }
Таким образом, работает следующее:
public class Main { private final static String data = "<tbody>\n" + " <tr>\n" + " <th></th>\n" + " <th>Weather</th>\n" + " <th><img src=\"http://localhost:8080/img/today\" /></th>\n" + " <th><img src=\"http://localhost:8080/img/today_1\" /></th>\n" + " <th><img src=\"http://localhost:8080/img/today_2\" /></th>\n" + " </tr>\n" + " <tr>\n" + " <td><img src=\"http://localhost:8080/img/location_1\" /></td>\n" + " <td> <a href=\"/Ney-tag/\" title=\"Ney\" target=\"_blank\" style=\"color:#7A2200;\">Ney</a> </td>\n" + " <td> 14 </td>\n" + " <td> 15 </td>\n" + " <td> 16 </td>\n" + " </tr>\n" + " <tr>\n" + " <td><img src=\"http://localhost:8080/img/location_2\" /></td>\n" + " <td> <a href=\"/Pana-tag/\" title=\"Pana\" target=\"_blank\" style=\"color:#7A2200;\">Pana</a> </td>\n" + " <td> 30 </td>\n" + " <td> 31 </td>\n" + " <td> 30 </td>\n" + " </tr>\n" + " <tr>\n" + " <td><img src=\"http://localhost:8080/img/location_3\" /></td>\n" + " <td> <a href=\"/Sin-tag/\" title=\"Sin\" target=\"_blank\" style=\"color:red;font-weight:bold;\">Sin</a> </td>\n" + " <td> 32 </td>\n" + " <td> 33 </td>\n" + " <td> 36 </td>\n" + " </tr>\n" + "</tbody>"; public static void main(String[] args) { Serializer serializer = new SerializerWithPreprocessor(); try { TBody tBody = serializer.read(TBody.class, data); serializer.write(tBody, System.out); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
Со следующим выводом:
<tbody> <tr> <th/> <th> <content>Weather</content> </th> <th> <img src="http://localhost:8080/img/today"/> </th> <th> <img src="http://localhost:8080/img/today_1"/> </th> <th> <img src="http://localhost:8080/img/today_2"/> </th> </tr> <tr> <td> <img src="http://localhost:8080/img/location_1"/> </td> <td> <a href="/Ney-tag/" title="Ney" target="_blank" style="color:#7A2200;"/> </td> <td> <content> 14 </content> </td> <td> <content> 15 </content> </td> <td> <content> 16 </content> </td> </tr> <tr> <td> <img src="http://localhost:8080/img/location_2"/> </td> <td> <a href="/Pana-tag/" title="Pana" target="_blank" style="color:#7A2200;"/> </td> <td> <content> 30 </content> </td> <td> <content> 31 </content> </td> <td> <content> 30 </content> </td> </tr> <tr> <td> <img src="http://localhost:8080/img/location_3"/> </td> <td> <a href="/Sin-tag/" title="Sin" target="_blank" style="color:red;font-weight:bold;"/> </td> <td> <content> 32 </content> </td> <td> <content> 33 </content> </td> <td> <content> 36 </content> </td> </tr> </tbody>
Возможно, вам придется поработать с регулярными выражениями в
replaceAll
, чтобы сделать его более удобным для пробелов.