如何让 JAXB 使用自定义命名空间前缀

问题描述 投票:0回答:2

使用 JAXB 将对象编组为 XML 时,它会自动生成名称空间前缀,如

ns2:
。遗憾的是,我必须与之通信的系统无法使用这些默认前缀(尽管 XML 完全有效),因此我想为所有不同的命名空间创建一个前缀映射。 XSD 也用于其他项目,所以我不想对其进行任何更改。

我在其他答案和其他网站上找到了 2 个解决方案:

  1. 使用命名空间前缀映射器类。听起来很完美,但不幸的是,这不再是一个选项,因为编组器上不再存在相关属性(使用

    jakarta.xml.bind:jakarta.xml.bind-api:4.0.0
    )。

  2. XmlNs
    中添加
    package-info.java
    注释。这似乎是剩下的唯一选项(除了编组后在 XML 文件中搜索/替换之外),但生成了此文件:所有 Java 类都是使用 Gradle 通过 XJC 任务从 XSD 生成的。手动添加此类注释到包信息文件将被下次运行的生成任务覆盖。

我的问题:有没有办法为 JAXB 提供我自己的前缀映射?或者有没有办法让XJC自动生成那些XmlNs注释?

xml gradle xsd jaxb xjc
2个回答
2
投票

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

0
投票

回答BATMAN_2008的问题...

下载 (zip) 包含一个独立的 Maven 项目,用于将给定的 XML workday-01.xml 文件解组为 JAXB 对象,然后将对象编组回 XML。

此演示已得到增强,演示如何使用两种替代方法为 XML 命名空间配置 自定义前缀

  1. package-info.java
    或者
  2. 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";
    }
};
© www.soinside.com 2019 - 2024. All rights reserved.