Java如何用@XmlValue注解处理简单内容

@XmlValue用于映射XML元素的纯文本内容,须与@XmlAttribute配合处理带属性的简单元素,且一个类中只能有一个@XmlValue字段,不能用于含子元素或多个文本字段的场景。

@XmlValue 用于将 Java 字段或属性映射为 XML 元素的**文本内容(simple content)**,即该元素**没有子元素,只有纯文本值**。它不能和 @XmlElement@XmlAttribute 等同时作用于同一个字段(会报错),且只能用于单个字段。

适用场景:映射带属性的简单元素

当 XML 元素既有文本内容,又有属性时,@XmlValue 配合 @XmlAttribute 是标准解法。例如:

29.99

对应 Java 类写法:

public class Price {
    @XmlAttribute
    public String currency;

    @XmlValue
    public BigDecimal value;
}

注意:@XmlValue 字段必须是**唯一的内容承载字段**,且类型需支持 JAXB 序列化(如 StringintBigDecimal 等)。

不能用于复杂内容或多个文本字段

以下情况 @XmlValue 不适用:

  • 元素包含子元素(如 JohnDoe)→ 应用 @XmlElement 嵌套对象
  • 一个类中声明多个 @XmlValue → 编译/运行时报错“more than one @XmlValue”
  • 想把文本和 CDATA 混合处理 → JAXB 默认不区分普通文本与 CDATA,需自定义 XmlAdapter

配合@XmlAccessorType控制访问策略

若字段为 private,需确保 JAXB 能访问到它。推荐显式设置访问器:

@XmlAccessorType(XmlAccessType.FIELD)
public class Price {
    @XmlAttribute
    private String currency;

    @XmlValue
    private BigDecimal value;
}

也可用 XmlAccessType.PROPERTY,此时需在 getter 上标注 @XmlValue

@XmlAccessorType(XmlAccessType.PROPERTY)
public class Price {
    private String currency;
    private BigDecimal value;

    @XmlAttribute
    public String getCurrency() { return currency; }
    public void setCurrency(String currency) { this.currency = currency; }

    @XmlValue
    public BigDecimal getValue() { return value; }
    public void setValue(BigDecimal value) { this.value = value; }
}

常见问题提醒

  • 如果字段类型是 String,JAXB 会原样序列化/反序列化,空格和换行会被保留(除非 XML 中用了 xml:space="preserve"
  • 反序列化时若文本为空字符串(),@XmlValue 字段会设为 null(对基本类型会抛异常,建议用包装类)
  • 不支持直接映射带命名空间前缀的文本内容;如需处理带 namespace 的简单元素,需结合 @XmlSchemapackage-info.java