2010-09-28 12 views
1

J'ai vu différents sujets discutant du type de problème que j'ai. Voici quelques-uns: http://www.mailinglistarchive.com/[email protected]/msg05061.html, Digester: Extracting node name).Caractère générique dans les règles XML du digesteur

Pourtant, je ne trouve toujours pas de solution à ce problème. Voici mes données XML:

<rows> 
    <row> 
     <firstname>Paul</firstname> 
     <lastname>Moris</lastname> 
    </row> 
    <row> 
     <firstname>John</firstname> 
     <lastname>Aiyer</lastname> 
     <age>35</age> 
    </row> 
</rows> 

Ce que je veux, c'est définir des règles XML qui me permettraient de mapper chaque ligne dans une carte. Je ne peux pas cartographier les éléments en faisant référence à leurs noms car tous les éléments possibles ne sont pas connus à l'avance.

J'espérais que quelque chose comme cela me permettra de le faire:

<digester-rules> 
    <pattern value="rows/row"> 
     <object-create-rule classname="Address"/> 
     <set-next-rule methodname="add" paramtype="java.lang.Object"/> 
     <set-properties-rule/> 

     <pattern value="*"> 
      <call-method-rule methodname="set" paramcount="2"/> 
      <call-param-rule paramnumber='0'/> 
      <call-param-rule paramnumber='1'/> 
     </pattern> 
    </pattern> 
</digester-rules> 

la mise en œuvre de l'adresse est:

public class Address { 
    Map<String,String> c= new HashMap<String,String>(); 

    public void set(String name, String value){ 
    c.put(name, value); 
    } 

    public String toString(){ 
    return c.toString(); 
    } 
} 

Malheureusement, quand je lance ce code je reçois deux adresses sont créés mais avec une carte sous-jacente vide. Lorsque j'utilise ExtendedBaseRules, rien n'est égalé.

Toute aide serait grandement appréciée.

Max.

Répondre

1

Je pense que Digester n'excelle pas dans l'analyse de xml hérité. Mais, heureusement, il est suffisamment extensible pour pouvoir être modifié dans certains de ces cas.

J'ai réussi à résoudre ce problème uniquement en utilisant l'API Java, pas avec les règles XML. Il est important d'utiliser la classe ExtendedBaseRules de Digester afin de faire correspondre les modèles rows/row/* et de sous-classer la CallParamRule standard afin de passer le nom de tag comme premier argument à la méthode addAddressLine() de la classe Address (j'ai renommé méthode set() dans votre classe Address to addAddressLine()).

Digester digester = new Digester();   
digester.setRules(new ExtendedBaseRules()); 
digester.setValidating(false); 
digester.addObjectCreate("rows", Addresses.class); 
digester.addObjectCreate("rows/row", Address.class); 
digester.addSetNext("rows/row", "add"); 
digester.addSetProperties("rows/row"); 
digester.addCallMethod("rows/row/*", "addAddressLine", 2); 
digester.addRule("rows/row/*", new TagNameAwarePathCallParamRule(0)); 
digester.addCallParam("rows/row/*", 1); 
Addresses addresses = (Addresses) digester.parse(new File(FILE_TO_PARSE)); 

La TagNameAwarePathCallParamRule de classe I mis en œuvre à cet effet:

public class TagNameAwarePathCallParamRule extends CallParamRule { 

    public TagNameAwarePathCallParamRule(int paramIndex) { 
     super(paramIndex); 
    } 

    public void end(String namespace, String name) { 
     if (bodyTextStack != null && !bodyTextStack.empty()) { 
      // what we do now is push one parameter onto the top set of 
      // parameters 
      Object parameters[] = (Object[]) digester.peekParams(); 
      parameters[paramIndex] = name; 
     } 

    } 
} 

Les classes I utilisé pour stocker la sortie de l'analyse syntaxique:

public class Addresses { 

    private List<Address> addresses = new ArrayList<Address>(); 

    public void add(Address a) { 
     addresses.add(a); 
    } 

    public List<Address> getAddresses() { 
     return Collections.unmodifiableList(addresses); 
    } 

    public String toString() { 
     StringBuilder sb = new StringBuilder(); 
     for (Address a : addresses) { 
      sb.append("Address: ").append(a.toString()).append(','); 
     } 
     return sb.toString(); 
    } 
} 


public class Address { 
    Map<String,String> c= new HashMap<String,String>(); 


public void addAddressLine(String name, String value){ 
    c.put(name, value); 
    } 

    public String toString(){ 
    return c.toString(); 
    } 
}