1

我还有一个更棘手的问题:

E.g. Person Class has: --String firstName --String lastName --Map stringMap

   Person person = new Person ();
   person.setFirstName("FirstName");
   person.setLastName("LastName");
   Map<String,String> stringMap = new HashMap<String,String>();
   stringMap.put("IwantThisKeyInXml","IwantThisValueInXml");
   stringMap.put("IDONTwantThisKeyInXml","IDONTwantThisValueInXml");


   InputStream iStream1 = classLoader.getResourceAsStream("person-binding.xml");
   List<Object> fileList = new ArrayList<Object>();
            fileList.add(iStream1);
   Map<String, Object> properties = new HashMap<String,Object>();               

   properties.put(JAXBContextProperties.OXM_METADATA_SOURCE,  fileList);
   JAXBContext ctx = JAXBContext.newInstance(new Class[] { GaDictionary.class, Person.class }, properties);

   Marshaller marshaller = ctx.createMarshaller();
   marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

   Writer output = new StringWriter();
   marshaller.marshal(person, output);
   System.out.println(output);

person-binding.xml 如下

   <?xml version="1.0"?>
   <xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="my.test.model"  xml-mapping-metadata-complete="true">
    <xml-schema
        element-form-default="QUALIFIED"/>
    <java-types>
        <java-type name="Person"  xml-accessor-type="NONE">
            <xml-root-element/>
            <xml-type prop-order="firstName lastName"/>
            <java-attributes>
                <xml-element java-attribute="firstName" name="first-name"/>
                <xml-element java-attribute="lastName" name="last-name"/>
                <xml-element java-attribute="stringMap" name="string-map"/>
            </java-attributes>
        </java-type>
      </java-types>
    </xml-bindings>

因此,结果的定义是:

   <?xml version="1.0" encoding="UTF-8"?>
   <person>
   <first-name>FirstName</first-name>
   <last-name>LastName</last-name>
   <string-map>
      <entry>
         <key>IwantThisKeyInXml</key>
         <value>IwantThisKeyInXml</value>
      </entry>
      <entry>
         <key>IDONTwantThisKeyInXml</key>
         <value>IDONTwantThisKeyInXml</value>
      </entry>
   </string-map>
   </person>

如何在 stringMap 上排除该条目?我尝试了虚拟访问方法,但也许我无法正确配置它?!我应该在编组后删除该值吗?这可能是一种智能且可维护的方式吗?

最后一个问题是我的属性是否为空值。如何配置 person-binding-xml 文件 (oxm.file) 以使相关 xml 标记为空?

我可以更改模型类,但如果可能的话,我宁愿不要添加任何代码行。(这就是我填充 xml 文件的原因)

所以我想得到的结果是:

 <?xml version="1.0" encoding="UTF-8"?>
   <person>
     <first-name>FirstName</first-name>
     <last-name>LastName</last-name>
     <string-map>
       <entry>
         <key>IwantThisKeyInXml</key>
         <value>IwantThisKeyInXml</value>
       </entry>
      </string-map>
  </person>

对于第二个相关问题:我尝试了 nillable="true" 但它不起作用!因此,例如,如果我有一个 stringMap 或 firstName 或其他东西的空值,我将分别获得并用任何主体关闭标签。

或者我想获得的另一种方式是:

 <?xml version="1.0" encoding="UTF-8"?>
   <person>
     <first-name>FirstName</first-name>
     <last-name>LastName</last-name>
     <string-map>
       <entry>
         <key>IwantThisKeyInXml</key>
         <value>IwantThisKeyInXml</value>
       </entry>
       <entry><!-- I have the entry but I have an empty value-->
         <key>KEY</key>
         <value></value>
       </entry>
      </string-map>
  </person>

谢谢大家

4

3 回答 3

4

在您的解决方案中,空策略是正确的想法,但它需要在 StringEntryType 的 value 属性上而不是在整个地图上。所以你的绑定文件应该包括这样的东西:

 <java-type name="StringEntryType">
        <java-attributes>
            <xml-element java-attribute="value" name="value">
                <xml-null-policy null-representation-for-xml="EMPTY_NODE"/>
            </xml-element>
        </java-attributes>
    </java-type>

您的解决方案看起来不错,但我想我还会发布一个替代解决方案,该解决方案利用您可能更喜欢的 MOXy 的只读和只写属性。在此示例中,变量 myMap 将在解组期间设置,但在编组期间将从 getModifiedMap 方法返回的 Map 将被调用。在 getModifiedMap 中,我们还将空值替换为空字符串,以便对空标签进行编组。

public class Root {

    public Map<String, String> myMap = new HashMap<String, String>();

    public Map<String, String> getModifiedMap(){
         Map modifiedMap = new HashMap<String, String>();       
         Set<Entry<String, String>> entries = myMap.entrySet();
         Iterator<Entry<String, String>> iter = entries.iterator();
         while(iter.hasNext()){
             Entry<String, String> nextEntry = iter.next();
             String nextKey = nextEntry.getKey();
             if(!nextKey.equals("omitthiskey")){
                 String nextValue = nextEntry.getValue();
                 if(nextValue == null){
                     nextValue ="";
                 }               
                 modifiedMap.put(nextKey, nextValue);
             }
         }
         return modifiedMap;
    }

    public void setModifiedMap(Map<String, String> newMap){
        //this method shouldn't get hit but needs to be present 
    }
}

并且相应的绑定文件将包含如下内容:

<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" package-name="test2" >
    <xml-schema element-form-default="QUALIFIED"/>  
    <java-types>
    <java-type name="Root"  xml-accessor-type="NONE">
        <xml-root-element/>
        <java-attributes>
            <xml-element java-attribute="myMap" name="myMap" read-only="true" />
            <xml-element java-attribute="modifiedMap" name="myMap" write-only="true"/>                      
        </java-attributes>
    </java-type>                    
    </java-types>
</xml-bindings>
于 2013-04-17T18:10:25.077 回答
1

如果您想防止某些 Map 条目被编组为 XML,您可以提供一个 XmlAdapter 来在编组时删除任何不需要的条目:

import java.util.Map;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public final class MyAdapter extends XmlAdapter<Map<String, String>, Map<String, String>> {

    private final String OMIT = "IDONTwantThisKeyInXml";

    @Override
    public Map<String, String> unmarshal(Map<String, String> arg0) throws Exception {
        return arg0;
    }

    @Override
    public Map<String, String> marshal(Map<String, String> arg0) throws Exception {
        if (arg0 != null) {
            arg0.remove(OMIT);
        }
        return arg0;
    }

}

不确定我是否理解您的第二个问题,您能否再解释一下您希望看到的行为?

希望这可以帮助,

瑞克

于 2013-04-11T19:27:11.640 回答
0

我找到了正确的解决方案:

        import java.util.HashMap;
        import java.util.Map;
        import java.util.Map.Entry;

        import javax.xml.bind.annotation.adapters.XmlAdapter;

        public final class StringMapAdapter extends XmlAdapter<StringAdapterMap, Map<String, String>> {

            private final String OMIT = "birthPlaceString";

            @Override
            public Map<String, String> unmarshal(StringAdapterMap v) throws Exception {
                 HashMap<String, String> hashMap = new HashMap<String, String>();
                 System.out.println("unmarshal"); 
                 for(StringEntryType myEntryType : v.entry) {
                     hashMap.put(myEntryType.key, myEntryType.value);
                  }
                  return hashMap;
            }

            @Override
            public StringAdapterMap marshal(Map<String, String> v) throws Exception {
                StringAdapterMap myMapType = new StringAdapterMap();
              for(Entry<String, String> entry : v.entrySet()) {
                  StringEntryType EntryType = new StringEntryType();
                   EntryType.key= entry.getKey();
                   EntryType.value = entry.getValue();
                   if (!OMIT.equals(EntryType.key))
                       myMapType.entry.add(EntryType);
              }
              return myMapType;

            }

StringAdapterMap 类:

        import java.util.ArrayList;
        import java.util.List;

        public class StringAdapterMap {
             public List<StringEntryType> entry = new ArrayList<StringEntryType>();

        }

StringEntryType 类:

        public class StringEntryType {

               public String key;

               public String value;

        }

在 oxm.file 中记得配置适配器

     <xml-element java-attribute="stringMap" name="string-map" >
      <xml-java-type-adapter value="it.cineca.jaxb.adapter.StringMapAdapter" />    
     </xml-element>
于 2013-04-17T14:47:59.427 回答