2016-10-25 6 views
9

Я использую среду SimpleXML для десериализации ответов на бэкэнд. Я сделал некоторые предположения об элементах. Некоторые элементы не отвечают этим требованиям. Например, я ожидаю, что элемент будет иметь дочерние элементы <ID> и <face>. Если мой пользователь не может видеть конкретный элемент, я мог бы получить ответ, как это:Как пропустить определенный элемент в SimpleXML

<list> 
    <voucher type="hiddenobject"> 
    <face>foo</face> 
    </voucher> 
    <voucher type="object"> 
    <ID>42</ID> 
    <face>bar</face> 
    </voucher> 
</list> 

Который дает мне ValueRequiredException для следующего класса десериализации:

@Root 
class Voucher { 
    @Element(name="ID") 
    private String id; 

    @Element 
    private String face; 
} 

Я хотел бы игнорировать эти объекты с типом hiddenobject. Я узнал о VisitorStrategy и реализован простой Visitor как так:

private static final class HiddenObjectVisitor implements Visitor { 

    @Override 
    public void read(Type type, NodeMap<InputNode> node) throws Exception { 
     String nodeType = node.getNode().getAttribute("type").getValue(); 

     if (nodeType != null && nodeType.equals("hiddenobject")) { 
      Log.d(TAG, "skipping node " + node); 
      node.getNode().skip(); 
     } 
    } 

    @Override 
    public void write(Type type, NodeMap<OutputNode> node) throws Exception { 
     // stub 
    } 
} 

и добавил Visitor к VisitorStrategy

VisitorStrategy strategy = new VisitorStrategy(new HiddenObjectVisitor()); 

ожидал, что это будет пропускать узлы во время десериализации. Я получаю записи журнала о том, что узел будет пропущен. Во всяком случае, VisitorStrategy, похоже, продолжает разбор узла, который должен быть пропущен, что приводит к ValueRequiredException.

Как я могу игнорировать узлы, имеющие данный атрибут? Можно ли использовать VisitorStrategy для выполнения этой задачи?

+0

целесообразно иметь класс ** ActiveVoucher ** расширяет ** ваучер **, где * ActiveVoucher * будет иметь требуемые атрибуты, а * ваучер * не будет иметь необходимых атрибутов? –

ответ

5

Вы могли бы объединить подход, предложенный Raniz с HiddenObjectVisitor. Аннотировать id с required=false, чтобы избежать ValueRequiredException, а затем воспользуйтесь HiddenObjectVisitor, чтобы пропустить некоторые из объектов Voucher во время десериализации.

На основе XML, который вы показали, id не требуется в файле XML, и это то, что указывает required=false. Но вы подразумеваете, что в ваших десериализованных объектах требуется id, поэтому вы можете отменить недопустимые объекты во время десериализации.

4

Одна вещь, которую вы можете сделать, это отметить ID как optional и включить атрибут типа, чтобы вы могли фильтровать после десериализации.

@Root 
class Voucher { 
    @Attribute 
    private String type; 

    @Element(name="ID", required=false) 
    private String id; 

    @Element 
    private String face; 
} 

Вы можете отфильтровать ваучера после того как они были deserialised:

// Deserialise the XML 
List<Voucher> vouchers = ...; 

// Filter the list of vouchers 
List<Voucher> nonHiddenVouchers = new ArrayList<>(); 
for (Voucher voucher : vouchers) { 
    if (!"hiddenobject".equals(voucher.getType())) { 
     nonHiddenVouchers.add(voucher); 
    } 
} 
+0

Спасибо, но я уже думал об этом. Я хотел бы оставить свои предположения относительно действительных объектов. Например, я использую ID в .equals(), где было бы плохо иметь нулевой идентификатор. – Jeremy