2

我需要从 Android 上的 java 对象生成 XML。XML 节点必须有明确的顺序。这是我得到的(这些字段按字母顺序排列):

<soap:Envelope xmlns:cwmp="urn:dslforum-org:cwmp-1-0" 
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope" 
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soap:Body>
    <cwmp:Inform>
      <CurrentTime>2013-06-07 07:11:20.561 UTC</CurrentTime>
      <DeviceId>
        <OUI>002615</OUI>
        <Manufacturer>Conexant</Manufacturer>
        <ProductClass>ADSL2+ IAD</ProductClass>
        <SerialNumber>00261559a496</SerialNumber>
      </DeviceId>
      <Event soapenc:arrayType="cwmp:EventStruct[1]">
        <EventStruct>
          <CommandKey></CommandKey>
          <EventCode>0 BOOTSTRAP</EventCode>
        </EventStruct>
      </Event>
      <ParameterList soapenc:arrayType="cwmp:ParameterValueStruct[1]">
        <ParameterValueStruct>
          <name>InternetGatewayDevice.DeviceInfo.SpecVersion</name>
          <value>1.0</value>
        </ParameterValueStruct>
      </ParameterList>
      <MaxEnvelopes>1</MaxEnvelopes>
      <RetryCount>0</RetryCount>
    </cwmp:Inform>
  </soap:Body>
  <soap:Header>
    <ID soap:mustUnderstand="1">
      <string>00001</string>
    </ID>
  </soap:Header>
</soap:Envelope>

这是我想要的:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soap:Header>
    <ID soap:mustUnderstand="1">
      <string>00001</string>
    </ID>
  </soap:Header>
  <soap:Body>
    <cwmp:Inform>
      <DeviceId>
        <Manufacturer>Conexant</Manufacturer>
        <OUI>002615</OUI>
        <ProductClass>ADSL2+ IAD</ProductClass>
        <SerialNumber>00261559a496</SerialNumber>
      </DeviceId>
      <Event soapenc:arrayType="cwmp:EventStruct[1]">
        <EventStruct>
          <EventCode>0 BOOTSTRAP</EventCode>
          <CommandKey></CommandKey>
        </EventStruct>
      </Event>
      <MaxEnvelopes>0</MaxEnvelopes>
      <CurrentTime>2013-06-07 07:16:54.128 UTC</CurrentTime>
      <RetryCount>0</RetryCount>
      <ParameterList soapenc:arrayType="cwmp:ParameterValueStruct[1]">
        <ParameterValueStruct>
          <name>InternetGatewayDevice.DeviceInfo.SpecVersion</name>
          <value>1.0</value>
        </ParameterValueStruct>
      </ParameterList>
    </cwmp:Inform>
  </soap:Body>
</soap:Envelope>

我已经对这个问题进行了更多调查。我发现 Xstream 在 Android 上以错误的顺序处理字段。Xstream 可以很好地处理 Java 项目中的字段。

@XStreamAlias("cwmp:Inform")
public class Inform {
    @XStreamAlias("DeviceId")
    private DeviceIdStruct      deviceId;

    @XStreamAlias("Event")
    private EventList           event;

    @XStreamAlias("MaxEnvelopes")
    private int                 maxEnvelopes;

    @XStreamAlias("CurrentTime")
    private Date                currentTime;

    @XStreamAlias("RetryCount")
    private int                 retryCount;

    @XStreamAlias("ParameterList")
    private ParameterValueList  parameterList;
}
4

2 回答 2

2

是我的答案。
我研究了这个问题并得出结论,Android 按字段类型的字母顺序返回字段。您可以继承 FieldKeySorter 来设置顺序。

首先,您需要创建将定义字段顺序的注释:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface XMLSequence {
    String[] value();
} 

并使用示例:

@XMLSequence({
        "accountIds",
        "addresses",
        "birthDate",
        "contact",
        "name",
        "status",
}) 

然后我继承了 FieldKeySorter :

public class SequenceFieldKeySorter implements FieldKeySorter {
    @Override
    public Map sort(final Class type, final Map keyedByFieldKey) {
        Annotation sequence = type.getAnnotation(XMLSequence.class);
        if (sequence != null) {
            final String[] fieldsOrder = ((XMLSequence) sequence).value();
            Map result = new OrderRetainingMap();
            Set<Map.Entry<FieldKey, Field>> fields = keyedByFieldKey.entrySet();
            for (String fieldName : fieldsOrder) {
                if (fieldName != null) {
                    for (Map.Entry<FieldKey, Field> fieldEntry : fields) {
                        if
(fieldName.equals(fieldEntry.getKey().getFieldName())) {
                            result.put(fieldEntry.getKey(),
fieldEntry.getValue());
                        }
                    }
                }
            }
            return result;
        } else {
            return keyedByFieldKey;
        }

    }
}

最后去:

XStream x = new XStream(new PureJavaReflectionProvider(
new FieldDictionary(new SequenceFieldKeySorter()))); 
于 2013-06-07T12:58:16.467 回答
1
  1. 您可以为要控制顺序的类实现此接口FieldKeySorter 。
  2. 你可以自己写一个注解,它不仅扩展了目标类,还通过反射在运行时实现了FieldKeySorter。最后替换实例来控制顺序。
于 2013-06-28T09:22:17.293 回答