2016-10-25 28 views
9

Używam framework SimpleXML do deserializacji odpowiedzi backendu. Podjąłem pewne założenia dotyczące elementów. Niektóre elementy nie spełniają tych wymagań. Na przykład oczekuję, że element będzie miał dziecko: <ID> i <face>. Jeśli mój użytkownik nie może zobaczyć konkretny element, mogę uzyskać odpowiedź tak:Jak pominąć określony element w SimpleXML

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

co daje mi ValueRequiredException na następny klasy deserializacji:

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

    @Element 
    private String face; 
} 

chciałbym zignorować te obiekty z typem hiddenobject. Dowiedziałem się o VisitorStrategy i wdrożył prosty Visitor tak:

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 
    } 
} 

i dodało ten Visitor do VisitorStrategy

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

spodziewa się, że będzie to pominąć węzły podczas deserializacji. Dostaję wpisy dziennika stwierdzające, że węzeł zostanie pominięty. W każdym razie, VisitorStrategy wydaje się kontynuować analizowanie węzła, który ma zostać pominięty, co daje w wyniku ValueRequiredException.

Jak mogę zignorować węzły o danym atrybucie? Czy do tego zadania można użyć VisitorStrategy?

+0

czy wskazane jest posiadanie klasy ** ActiveVoucher ** rozszerza ** Voucher **, gdzie * ActiveVoucher * wymaga atrybutów, a * Voucher * nie ma wymaganych atrybutów? –

Odpowiedz

5

Można prawdopodobnie łączyć podejście zaproponowane przez Raniz z HiddenObjectVisitor. Adnotacja id z required=false, aby uniknąć ValueRequiredException, a następnie użyj swojego HiddenObjectVisitor, aby pominąć niektóre obiekty Voucher podczas deserializacji.

Na podstawie przedstawionego kodu XML plik id nie jest wymagany w pliku XML, co oznacza required=false. Ale sugerujesz, że id jest wymagany w twoich deserializowanych obiektach, więc możesz odrzucić nieważne obiekty w czasie deserializacji.

4

Jedną z rzeczy, którą można zrobić, to oznaczyć ID jako optional i dołączyć atrybut type, aby można było filtrować po deserialization.

@Root 
class Voucher { 
    @Attribute 
    private String type; 

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

    @Element 
    private String face; 
} 

Następnie można filtrować talony po ich 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

Dzięki, ale już o tym myślałem. Chciałbym zachować moje założenia dotyczące ważnych obiektów. Na przykład używam ID w .equals(), gdzie byłoby źle mieć zerowy identyfikator. – Jeremy