Digester XML 规则中的通配符

发布于 2024-09-25 04:10:49 字数 1841 浏览 11 评论 0原文

我见过不同的线程讨论我遇到的问题。以下是一些: http://www.mailinglistarchive.com/ [电子邮件受保护]/msg05061.htmlDigester:提取节点名称)。

然而,我仍然找不到这个问题的解决方案。这是我的 XML 数据:

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

我想要的是定义 XML 规则,允许我将每一行映射到一个映射中。我无法通过引用元素的名称来映射元素,因为并非所有可能的元素都是预先知道的。

我希望这样的事情可以让我做到这一点:

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

地址的实现是:

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();
  }
}

不幸的是,当我运行此代码时,我得到了两个已创建的地址,但底层映射为空。当我使用 ExtendedBaseRules 时,甚至没有任何匹配。

任何帮助将不胜感激。

最大限度。

I've seen different threads that discuss the kind of issue I have. Here are few: http://www.mailinglistarchive.com/[email protected]/msg05061.html, Digester: Extracting node name).

Yet, I still can't find a solution to this issue. Here is my XML data:

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

What I want is define XML rules that would allow me to map each row into a map. I can't map the elements by referring to their names because not all possible elements are known upfront.

I was hoping that something like this would allow me to do this:

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

the implementation of Address is:

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();
  }
}

Unfortunately, when I run this code I get two addresses that are created but with empty underlying map. When I use ExtendedBaseRules, nothing is even matched.

Any help would be much appreciated.

Max.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

疯狂的代价 2024-10-02 04:10:49

我认为 Digester 在解析遗留 xml 方面并不擅长。但幸运的是,它具有足够的可扩展性,可以对其进行调整以在某些情况下工作。

我仅通过使用 java api 解决了这个问题,而不是使用 xml 规则。重要的是使用 Digester 的 ExtendedBaseRules 类来匹配模式 rows/row/* 并子类化标准 CallParamRule 以便将标记名称作为第一个参数传递给类 Address 的方法 addAddressLine() (我将将您的类 Address 中的方法 set() 更改为 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));

我为此目的实现的类 TagNameAwarePathCallParamRule:

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

    }
}

我用于存储解析输出的类:

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();
  }
}

I think that Digester does not excel in parsing legacy xml. But, fortunately, it's extensible enough that it can be tweaked to work in some of these cases.

I managed to resolve this problem only by using the java api, not with the xml rules. It's important to use the Digester's ExtendedBaseRules class in order to match the patterns rows/row/* and to subclass the standard CallParamRule in order to pass the tag name as the first argument to the method addAddressLine() of the class Address (I renamed the method set() in your class 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));

The class TagNameAwarePathCallParamRule I implemented for this purpose:

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

    }
}

The classes I used for storing the output of the parsing:

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();
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文