Не парсер 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 2

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, чтобы сделать его более удобным для пробелов.