【问题标题】:Jax-WS - To Remove Empty Tags from Request XMLJax-WS - 从请求 XML 中删除空标签
【发布时间】:2012-06-26 20:34:26
【问题描述】:

我正在尝试使用提供商公开的 Web 服务。提供者最后严格检查请求 xml 不应包含没有值的标签。

我正在使用 Jax-WS。如果我没有在特定对象中设置值,它将作为空标签发送并且标签存在。 PFB 示例说明了我的问题。

客户端 XML:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:host="http://host.testing.webservice.com/">
   <soapenv:Header/>
   <soapenv:Body>
      <host:testingMathod>
         <arg0>
            <PInfo>
               <IAge>45</IAge>
               <strName>Danny</strName>
            </PInfo>
            <strCorrId>NAGSEK</strCorrId>
            <strIpAddress></strIpAddress>
         </arg0>
      </host:testingMathod>
   </soapenv:Body>
</soapenv:Envelope>

在这种情况下,没有给出 IpAddress 的值,因此发送了空标签。

因此,请让我们知道需要做什么才能删除请求 xml 中的空标签。 Handlerchain 是唯一的解决方案吗?

谢谢, 纳文。

【问题讨论】:

  • 没有人知道解决方案吗?不然这么简单,没人愿​​意回复?请帮帮我..
  • 我是 EclipseLink JAXB (MOXy) 负责人,我添加了一个应该有帮助的答案:stackoverflow.com/a/11249220/383861

标签: xml web-services jaxb jax-ws moxy


【解决方案1】:

注意:我是EclipseLink JAXB (MOXy) 的负责人,也是JAXB (JSR-222) 专家组的成员。

默认情况下 MOXy 像其他 JAXB 实现一样不会将元素编组为空值:

可能的问题

我相信strIpAddress 属性不为空,而是包含一个空字符串 ("") 的值。这会导致空元素被写出。

package forum11215485;

import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {

    String nullValue;
    String emptyStringValue;
    String stringValue;

}

演示

package forum11215485;

import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

        Root root = new Root();
        root.nullValue = null;
        root.emptyStringValue = "";
        root.stringValue = "Hello World";

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

输出

注意nullValue 字段中没有元素被编组,emptyStringValue 字段被编组为空元素。

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <emptyStringValue></emptyStringValue>
   <stringValue>Hello World</stringValue>
</root>

解决方案 #1 - 确保属性设置为 null 而不是 ""

解决方案 #2 - 编写一个将 "" 转换为 null 的 XmlAdapter

XmlAdapter 是一种 JAXB 机制,它允许将一个对象编组为另一个对象。

字符串适配器

以下XmlAdapter 会将空字符串编组为空。这将导致它们不会出现在 XML 表示中。

package forum11215485;

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

public class StringAdapter extends XmlAdapter<String, String> {

    @Override
    public String unmarshal(String v) throws Exception {
        return v;
    }

    @Override
    public String marshal(String v) throws Exception {
        if(null == v || v.length() == 0) {
            return null;
        }
        return v;
    }

}

包裹信息

XmlAdapter 使用 @XmlJavaTypeAdapter 注释挂钩。下面是一个在包级别挂钩它的示例,以便它适用于包中字符串类型的字段/属性。更多信息请见:http://blog.bdoughan.com/2012/02/jaxb-and-package-level-xmladapters.html

@XmlJavaTypeAdapter(value=StringAdapter.class, type=String.class)
package forum11215485;

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

输出

现在运行演示代码的输出如下:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <stringValue>Hello World</stringValue>
</root>

【讨论】:

  • +1 因为你是一个勤奋的人!也因为我同意如果有一些空字符串,适配器是删除它的方法。
  • 如果在处理过程中未将这些属性值设置为值,则将这些属性值设置为 null 是一种排除它们的干净方法,感谢您的提示!
【解决方案2】:

这是您正在使用的 XML 序列化程序的问题(如果您没有做一些特殊的事情,它应该是 JAXB)。

序列化程序的“空策略”应该是可配置的,但我认为 JAXB 是不可能的。如果您使用MOXy,您可以使用XmlMarshalNullRepresentation.ABSENT_NODE 来不写入节点(如果它为空)。实现应该是这样的:

class MyClass {

    // ... here are your other attributes

    @XmlElement (name = "strIpAddress")
    @XmlNullPolicy(nullRepresentationForXml = XmlMarshalNullRepresentation.ABSENT_NODE)
    String strIpAddress = null;

}

PS:也许您还需要定义@XmlNullPolicyemptyNodeRepresentsNull 参数。

有关此主题的更多信息,请查看this question

【讨论】:

  • +1 表示@XmlNullPolicy。但是,我认为该问题与包含空字符串的 strIpAddress 有关。我添加了一个答案,演示如何使用XmlAdapter 解决这个问题:stackoverflow.com/a/11249220/383861
【解决方案3】:

当我序列化一个我不能使用注释的类时,这对我有用 (LogRecord):

            JAXBContext jc = JAXBContext.newInstance(LogRecord.class);
            JAXBElement<LogRecord> je = new JAXBElement<>(new QName("log"), LogRecord.class, record);
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.setAdapter(new XmlAdapter<String,String>() {
                @Override
                public String marshal(String v) throws Exception {
                    if(null == v || v.length() == 0) {
                        return null;
                    }
                    return v;
                }
                @Override
                public String unmarshal(String v) throws Exception {
                    return v;
                }
            });
            ByteArrayOutputStream xml = new ByteArrayOutputStream();
            marshaller.marshal(je, xml);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    • 2015-12-06
    • 2010-12-29
    • 1970-01-01
    • 2012-04-02
    • 2012-01-26
    • 1970-01-01
    相关资源
    最近更新 更多