使用 JAXB 将 XML CDATA 字符串解组为文字
Unmarshaling XML CDATA strings as literals using JAXB
考虑以下简单的 XML
字符串:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<example>
<value name="test">abcd</value>
</example>
下面的代码定义了2个Java
类(Example.class
和Value.class
)可以用来产生上面的XML
输出,对于字符串值 abcd
:
@XmlRootElement(name = "example")
public class Example {
private Value value;
private Example() {}
public Value getValue() { return value; }
public void setValue(Value value) { this.value = value; }
@XmlAccessorType(XmlAccessType.FIELD)
private static final class Value {
@XmlValue
private String value;
@XmlAttribute(name="name")
private String name;
public Value() {}
public String getValue() { return value; }
public void setValue(String value) { this.value = value; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
}
要将上面的 XML
字符串解组(反序列化)到生成它的原始 Example
对象中,可以使用以下代码:
public static void main(String[] args) throws Exception {
JAXBContext context = JAXBContext.newInstance(Example.class);
String input = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
"<example>\n" +
" <value name=\"test\">abcd</value>\n" +
"</example>";
Unmarshaller um = context.createUnmarshaller();
Example v = (Example)um.unmarshal(new ByteArrayInputStream(input.getBytes()));
System.out.println(v.getValue().getValue());
}
但是,如果上述 main()
方法中的字符串值从 abcd
更改为 abcd<>
或任何其他 CDATA
字符串,解组程序将抛出异常:
org.xml.sax.SAXParseException; The content of elements must consist of well-formed character data or markup.
一个proposed solution是用一个自定义的DOMHandler
加上XmlAnyElement
注解,但是好像不行。
是否有任何方法可以将 abcd<>
字符串反序列化为文字(即不将其包含在 CDATA
部分中)?
唯一的方法是用字符引用 &qout;&
等替换特殊字符 "&'<>
我认为您必须将 xml 字符串中的特殊字符替换为以下内容。
abcd<> instead of `abcd<>`
您是否尝试过创建一种在解组之前附加 CDATA 标记的方法?
public String addCdataTags (String yourString){
return "<![CDATA[" + yourString + "]]>"
}
这应该处理那些被错误地视为 xml 元素标签的 CDATA 字符串
Is there any way of deserializing the abcd<> string as a literal
(i.e., without enclosing it in a CDATA section)?
不,因为您的 XML 无效。
The problem is to try to unmarshal an unknown input, therefore such
preprocessing is not possible
您需要确保输入有效 XML 才能使用任何 XML 工具。
无效XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<example>
<value name="test">abcd<></value>
</example>
当您尝试解析上述 XML 时,您遇到了以下异常。异常来自 JAXB 使用的底层解析器。 XML 解析器依赖于代表元素标签的尖括号。将它们包含在元素内容中时必须特别小心。
org.xml.sax.SAXParseException; The content of elements must consist of well-formed character data or markup.
使用已解析的字符数据变得有效
使 XML 有效的一种方法是将 <
替换为 <
并将 >
替换为 >
。您的 JAXB 实现会将 XML 值 abcd<>
解组为 String
值 abcd<>
.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<example>
<value name="test">abcd<></value>
</example>
使用字符数据变得有效
另一种使 XML 有效的方法是将字符内容包装在 CDATA 块中。 JAXB 会将 <![CDATA[abcd<>]]>
解组为 abcd<>
。在封送处理时,它会将内容放入 XML 作为 abcd<>
.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<example>
<value name="test"><![CDATA[abcd<>]]></value>
</example>
考虑以下简单的 XML
字符串:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<example>
<value name="test">abcd</value>
</example>
下面的代码定义了2个Java
类(Example.class
和Value.class
)可以用来产生上面的XML
输出,对于字符串值 abcd
:
@XmlRootElement(name = "example")
public class Example {
private Value value;
private Example() {}
public Value getValue() { return value; }
public void setValue(Value value) { this.value = value; }
@XmlAccessorType(XmlAccessType.FIELD)
private static final class Value {
@XmlValue
private String value;
@XmlAttribute(name="name")
private String name;
public Value() {}
public String getValue() { return value; }
public void setValue(String value) { this.value = value; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
}
要将上面的 XML
字符串解组(反序列化)到生成它的原始 Example
对象中,可以使用以下代码:
public static void main(String[] args) throws Exception {
JAXBContext context = JAXBContext.newInstance(Example.class);
String input = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
"<example>\n" +
" <value name=\"test\">abcd</value>\n" +
"</example>";
Unmarshaller um = context.createUnmarshaller();
Example v = (Example)um.unmarshal(new ByteArrayInputStream(input.getBytes()));
System.out.println(v.getValue().getValue());
}
但是,如果上述 main()
方法中的字符串值从 abcd
更改为 abcd<>
或任何其他 CDATA
字符串,解组程序将抛出异常:
org.xml.sax.SAXParseException; The content of elements must consist of well-formed character data or markup.
一个proposed solution是用一个自定义的DOMHandler
加上XmlAnyElement
注解,但是好像不行。
是否有任何方法可以将 abcd<>
字符串反序列化为文字(即不将其包含在 CDATA
部分中)?
唯一的方法是用字符引用 &qout;&
等替换特殊字符 "&'<>
我认为您必须将 xml 字符串中的特殊字符替换为以下内容。
abcd<> instead of `abcd<>`
您是否尝试过创建一种在解组之前附加 CDATA 标记的方法?
public String addCdataTags (String yourString){
return "<![CDATA[" + yourString + "]]>"
}
这应该处理那些被错误地视为 xml 元素标签的 CDATA 字符串
Is there any way of deserializing the abcd<> string as a literal (i.e., without enclosing it in a CDATA section)?
不,因为您的 XML 无效。
The problem is to try to unmarshal an unknown input, therefore such preprocessing is not possible
您需要确保输入有效 XML 才能使用任何 XML 工具。
无效XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<example>
<value name="test">abcd<></value>
</example>
当您尝试解析上述 XML 时,您遇到了以下异常。异常来自 JAXB 使用的底层解析器。 XML 解析器依赖于代表元素标签的尖括号。将它们包含在元素内容中时必须特别小心。
org.xml.sax.SAXParseException; The content of elements must consist of well-formed character data or markup.
使用已解析的字符数据变得有效
使 XML 有效的一种方法是将 <
替换为 <
并将 >
替换为 >
。您的 JAXB 实现会将 XML 值 abcd<>
解组为 String
值 abcd<>
.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<example>
<value name="test">abcd<></value>
</example>
使用字符数据变得有效
另一种使 XML 有效的方法是将字符内容包装在 CDATA 块中。 JAXB 会将 <![CDATA[abcd<>]]>
解组为 abcd<>
。在封送处理时,它会将内容放入 XML 作为 abcd<>
.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<example>
<value name="test"><![CDATA[abcd<>]]></value>
</example>