使用 JAXB 将对象编组为 XML 时,它会自动生成名称空间前缀,如
ns2:
。遗憾的是,我必须与之通信的系统无法使用这些默认前缀(尽管 XML 完全有效),因此我想为所有不同的命名空间创建一个前缀映射。 XSD 也用于其他项目,所以我不想对其进行任何更改。
我在其他答案和其他网站上找到了 2 个解决方案:
使用命名空间前缀映射器类。听起来很完美,但不幸的是,这不再是一个选项,因为编组器上不再存在相关属性(使用
jakarta.xml.bind:jakarta.xml.bind-api:4.0.0
)。
在
XmlNs
中添加package-info.java
注释。这似乎是剩下的唯一选项(除了编组后在 XML 文件中搜索/替换之外),但生成了此文件:所有 Java 类都是使用 Gradle 通过 XJC 任务从 XSD 生成的。手动添加此类注释到包信息文件将被下次运行的生成任务覆盖。
我的问题:有没有办法为 JAXB 提供我自己的前缀映射?或者有没有办法让XJC自动生成那些XmlNs注释?
HiSrc HyperJAXB Annox提供了一个XJC插件,可以将Java注释添加到您生成的
package-info.java
中。您可以添加注释来指定自定义 xmlns
。要使用它,请将 jar(如下)添加到您的 XJC 类路径,并将此参数添加到您的 XJC 调用中,-Xannotate
。
XJC 附加罐
<groupId>org.patrodyne.jvnet</groupId>
<artifactId>hisrc-hyperjaxb-annox-plugin</artifactId>
<version>2.1.0</version>
在绑定文件中的任意一个
annox
处配置 complexType
扩展名,就像这样...
绑定示例
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings jaxb:version="3.0"
xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:annox="http://jvnet.org/basicjaxb/xjc/annox"
jaxb:extensionBindingPrefixes="annox"
>
<jaxb:bindings schemaLocation="PurchaseOrder.xsd" node="/xsd:schema" >
<jaxb:bindings node="xsd:element[@name='purchaseOrder']/xsd:complexType">
...
<annox:annotatePackage>
@jakarta.xml.bind.annotation.XmlSchema(
xmlns = {
@jakarta.xml.bind.annotation.XmlNs(prefix = "po", namespaceURI = "http://example.org/po")
})
</annox:annotatePackage>
...
</jaxb:bindings>
</jaxb:bindings>
每次在构建中运行 XJC 操作时,
package-info.java
类应包含您定义的 XmlNs
前缀。
免责声明:我是分叉 HiSrc 项目的维护者。
顺便说一句,在 Eclipse JAXB 实现中,
NamespacePrefixMapper
及其属性可以在以下位置找到:
Mapper: org.glassfish.jaxb.runtime.marshaller.NamespacePrefixMapper
Used By: org.glassfish.jaxb.runtime.v2.runtime.MarshallerImpl
Property: org.glassfish.jaxb.namespacePrefixMapper
回答BATMAN_2008的问题...
此 下载 (zip) 包含一个独立的 Maven 项目,用于将给定的 XML workday-01.xml 文件解组为 JAXB 对象,然后将对象编组回 XML。
此演示已得到增强,演示如何使用两种替代方法为 XML 命名空间配置 自定义前缀:
或者package-info.java
.org.glassfish.jaxb.namespacePrefixMapper
将其解压到本地文件夹后,您可以使用以下命令运行测试:
mvn -Ptest clean test
输出显示两个替代的自定义 XML 命名空间前缀:
"wd:"
和 "workday:"
。
调试工作日根 1(wd):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xmlns:wd="urn:com.workday/bsvo">
<wd:Put_Absence_Input_Request wd:version="v39.2">
<wd:Absence_Input_Data>
<wd:Batch_ID>Import 15022023</wd:Batch_ID>
<wd:Worker_Reference>
<wd:ID wd:type="Employee_ID">1741538</wd:ID>
</wd:Worker_Reference>
<wd:Absence_Component_Reference>
<wd:ID wd:type="Accrual_Code">FRA_Shadow_Accrual_for_Time_Offs_Impacting_Accrual_of_Paid_Annual_Leave_CP</wd:ID>
</wd:Absence_Component_Reference>
<wd:Start_Date>2023-01-01</wd:Start_Date>
<wd:End_Date>2023-01-31</wd:End_Date>
<wd:Reference_Date>2023-01-15</wd:Reference_Date>
<wd:Hours>2.08</wd:Hours>
<wd:Adjustment>false</wd:Adjustment>
</wd:Absence_Input_Data>
</wd:Put_Absence_Input_Request>
</root>
第一个输出使用
"wd:"
前缀封送 XML。此前缀在 root.xjb 绑定文件中配置,以自定义 JAXB 生成的类。结果是一个带有声明的 package-info
前缀的自定义 "wd:
类。此方法在 build 时声明前缀。
package-info.java
@jakarta.xml.bind.annotation.XmlSchema(namespace = "urn:com.workday/bsvo", elementFormDefault = jakarta.xml.bind.annotation.XmlNsForm.QUALIFIED, xmlns = {
@jakarta.xml.bind.annotation.XmlNs(prefix = "wd", namespaceURI = "urn:com.workday/bsvo")
})
package com.workday.bsvo;
调试工作日根2(工作日):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xmlns:workday="urn:com.workday/bsvo">
<workday:Put_Absence_Input_Request workday:version="v39.2">
<workday:Absence_Input_Data>
<workday:Batch_ID>Import 15022023</workday:Batch_ID>
<workday:Worker_Reference>
<workday:ID workday:type="Employee_ID">1741538</workday:ID>
</workday:Worker_Reference>
<workday:Absence_Component_Reference>
<workday:ID workday:type="Accrual_Code">FRA_Shadow_Accrual_for_Time_Offs_Impacting_Accrual_of_Paid_Annual_Leave_CP</workday:ID>
</workday:Absence_Component_Reference>
<workday:Start_Date>2023-01-01</workday:Start_Date>
<workday:End_Date>2023-01-31</workday:End_Date>
<workday:Reference_Date>2023-01-15</workday:Reference_Date>
<workday:Hours>2.08</workday:Hours>
<workday:Adjustment>false</workday:Adjustment>
</workday:Absence_Input_Data>
</workday:Put_Absence_Input_Request>
</root>
第二个输出使用
"workday:"
前缀封送 XML。此前缀是使用自定义 JAXB 编组器在 WorkdayTest 类中配置的。此方法在 run 时声明前缀并覆盖 package-info
配置。
WorkdayTest.java
...
marshaller.setProperty("org.glassfish.jaxb.namespacePrefixMapper", NAMESPACE_PREFIX_MAPPER);
...
public static final NamespacePrefixMapper NAMESPACE_PREFIX_MAPPER = new NamespacePrefixMapper()
{
@Override
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix)
{
return "workday";
}
};