使用 Java 进行 XML 解析(JAXB 和根元素)



我正在用Java为一个简单的xml结构编写XML解析器,该结构的结构以

<Document xmlns="some value" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

除了这一行之外,我能够很好地读取整个XML结构。我能够使用 JAXB 解析和读取相应的 JAVA POJO,而无需 xmlns 属性。但是,如果我添加解析器会引发异常。

我尝试过的,

@XmlRootElement(name = "Document")
static class UserMetaData {
@XmlAttribute(name = "xmlns:xsi", required = true)
String xmlnsXsi;
@XmlAttribute(name = "xmlns", required = true)
String xmlns;
@XmlElement(name = "User", required = true, nillable = false)
User userRecord;
}

Edit

成功使用以下代码:

@Test
public void unmarshal() throws JAXBException {
JAXBContext context = JAXBContext.newInstance(UserData.class);
Unmarshaller unmarshaler = context.createUnmarshaller();
StringReader reader = new StringReader("<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.002.001.03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><User/></Document>");
UserData result = (UserData) unmarshaler.unmarshal(reader);
System.out.println(result.userRecord);
}

还有豆子:

@XmlRootElement(name = "Document", namespace="urn:iso:std:iso:20022:tech:xsd:pain.002.001.03")
public class UserData {
@XmlElement(name = "User", required = true, nillable = false)
public  User userRecord;
}

假设您有:

<Document xmlns="http://test.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

删除这些:

@XmlAttribute(name = "xmlns:xsi", required = true)
String xmlnsXsi;
@XmlAttribute(name = "xmlns", required = true)
String xmlns;

无需将命名空间映射为属性。

您需要使用命名空间定义根元素:

@XmlRootElement(name = "Document", namespace= "http://test.com")

进一步解释一下。假设在 XML 中,您有 2 种不同类型的用户。一个用户是具有名称、登录名和密码的数据库用户,另一个用户具有名称和证书。

您可以创建类似以下内容的内容:

<user name="">
<login></login>
<password></password>
<cert></cert>
</user>

但这种结构不符合要求。用户定义不同。因此,您可能需要创建 2 个定义:

<user name="">
<login></login>
<password></password>
</user>
<user name="">
<cert></cert>
</user>

但是如何在同一个XML中区分这两个定义呢?这就是命名空间的目的。它们允许在同一 XML 文档中使用具有相同名称但内容不同的标签:

<Document>
<user name="" xmlns="http://user1.com">
<login></login>
<password></password>
</user>
<user name="" xmlns="http://user2.com">
<cert></cert>
</user>
</Document>

第一个用户标记在 http://user1.com 命名空间中定义,第二个用户标记在 http://user2.com 命名空间中定义。它们不再冲突,并被视为具有不同定义的 2 个不同名称。

但是,为每个标签提及 xmlns="http://user1.com" 或 xmlns="http://user2.com" 是很乏味的。命名空间别名在这里有很大帮助。您可以在根元素中定义任何命名空间别名,并使用别名作为标记前缀。对于我们的示例,我们将定义 2 个别名 user1 和 user2,并将它们用作前缀:

<Document xmlns:user1="http://user1.com" xmlns:user2=xmlns="http://user2.com">
<user1:user name="">
<login></login>
<password></password>
</user>
<user2:user name="">
<cert></cert>
</user>
</Document>

这样,XML 的定义就更短、更清晰了。

但请记住,别名只是助手。XML 解析器和验证器总是用完整的命名空间替换别名,例如 http://user1.com" 或 http://user2.com 用于标记比较。

在您的示例中,添加 xmlns="something" 会将 XML 默认命名空间的根元素的默认命名空间重新定义为"something"。

当 JAXB 尝试取消封送对象时,它会在 XML 中查找空命名空间中的文档,但找不到它,因为文档是在"某物"命名空间中定义的。

最新更新