【发布时间】:2022-01-19 23:06:34
【问题描述】:
我发现 XmlPath 的一个“奇怪”行为有时会提供与 XPath 相关联的 an object,有时只提供 null。
我花了几个小时才发现它是如何发生的,这样您就不必浪费时间了。
但我仍然对这种行为的“为什么”感到好奇。
要重新创建案例,您将需要 eclipselink 和(使用较新的 Java)jaxb-api:
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.7.10</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
XML 文件非常简单(lorem.xml):
<?xml version="1.0" encoding="UTF-8" ?>
<lorem>
<name>Smith</name>
<foo>
<bar x="5">
<ipsum>8888</ipsum>
</bar>
</foo>
</lorem>
Lorem.java
package forum;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlRootElement(name = "lorem")
@XmlAccessorType(XmlAccessType.FIELD)
public class Lorem
{
@XmlElement
Foo foo;
@XmlPath("foo/bar")
Bar obj3;
@XmlPath("name/text()")
String name;
}
Foo.java
package forum;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
@XmlAccessorType(XmlAccessType.FIELD)
public class Foo
{
@XmlElement
private Bar bar;
}
Bar.java
package forum;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
@XmlAccessorType(XmlAccessType.FIELD)
public class Bar
{
@XmlAttribute(name = "x")
public String valX;
@XmlElement
private String ipsum;
}
DemoLorem.java
package forum;
import java.io.File;
import java.util.Properties;
import javax.xml.bind.JAXB;
public class DemoLorem
{
public static void main(String[] args) throws Exception
{
Properties props = System.getProperties();
props.setProperty("javax.xml.bind.context.factory", "org.eclipse.persistence.jaxb.JAXBContextFactory");
props.setProperty("javax.xml.bind.JAXBContextFactory", "org.eclipse.persistence.jaxb.JAXBContextFactory");
Lorem lorem = JAXB.unmarshal(new File("lorem.xml"), Lorem.class);
System.out.println(lorem.obj3.valX);
JAXB.marshal(lorem, System.out);
}
}
在这种情况下,我们会收到以下错误:
Exception in thread "main" java.lang.NullPointerException: Cannot read field "valX" because "lorem.obj3" is null
at forum.DemoLorem.main(DemoLorem.java:19)
"lorem.obj3" 为 null 是 foo 的子对象。
但是当我们像这样修改 Lorem.java 时:
// @XmlElement
// private Foo foo;
突然一切正常,我们得到:
5 <--- this is value of lorem.obj3.valX
<?xml version="1.0" encoding="UTF-8"?>
<lorem>
<foo>
<bar x="5">
<ipsum>8888</ipsum>
</bar>
</foo>
<name>Smith</name>
</lorem>
为了确保 XPath 在这两种情况下都能正常工作,有 name 字段作为参考。
当我们没有引用父对象的 XmlElement (foo) 时,XPath 被正确解析并得到 (bar)。
在相反的情况下,bar 为空。为什么 XPath 没有解析?
我明白了,我可以从foo 得到bar。为什么添加一个引用会影响(中断)另一个?
为什么?
【问题讨论】: