如何在 Jakarta JAX-B 编组期间组合并包含自定义“NamespacePrefixMapper”和“HashMap”中的名称空间,

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

我正在尝试使用

Jakarta JAXB marshaller
封送 Java 对象,除了在生成的 XML 中包含命名空间之外,一切都运行良好。

我的类

Map
CustomNamespaces
中几乎没有自定义命名空间,并且在扩展
StandardNamespaces
NamespacePrefixMapper
中也几乎没有标准命名空间。我正在尝试将它们组合起来并将其添加到 Jakarta JAXB Marshaller,但由于某种原因,它无法按预期工作,并且它要么添加所有命名空间,要么不添加我的
CustomNamespaces
HahsMap 中存在的命名空间。

以下是我的

StandardNamespaces.class

import java.util.HashMap;
import java.util.Map;
import org.eclipse.persistence.oxm.NamespacePrefixMapper;

public class StandardNamespaces extends NamespacePrefixMapper {

  public static final Map<String, String> NAMESPACE_MAP =
      Map.of(
          "http://www.w3.org/2001/XMLSchema-instance", "xsi",
          "urn:abc:xyz:xsd:2", "abc",
          "urn:abc:xyz-query:xsd:2", "abcq",
          "http://www.example.org/namespaces/Standard", "sbdh",
          "http://www.w3.org/2003/05/soap-envelope/", "soap");

  private Map<String, String> namespaceMap;

  public StandardNamespaces(final Map<String, String> namespaceMap) {
    this.namespaceMap = namespaceMap;
  }

  public StandardNamespaces() {
    this(new HashMap<>(NAMESPACE_MAP));
  }

  @Override
  public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
    return namespaceMap.getOrDefault(namespaceUri, suggestion);
  }
}

以下是我的

CustomNamespaces.class
,其中包含带有名称空间的HashMap:

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

public class CustomNamespaces {

  private static CustomNamespaces context;
  private final Map<String, String> NAMESPACES;

  private CustomNamespaces() {
    this.NAMESPACES = new HashMap<>();
  }

  public static CustomNamespaces getContext() {
    if (context == null) {
      context = new CustomNamespaces();
    }
    return context;
  }

  // Add all the Namespaces that are defined.
  public synchronized void populateNamespaces(final String namespaceURI, final String prefix) {
    if (!NAMESPACES.containsKey(prefix)&& !NAMESPACES.containsValue(prefix)&& namespaceURI != null&& prefix != null) {
      NAMESPACES.put(namespaceURI, prefix);
    }
  }

  // Method that returns the saved Document namespaces.
  public Map<String, String> getAllNamespaces() {
    return NAMESPACES;
  }

  // Reset the event namespaces after completing.
  public synchronized void resetAllNamespaces() {
    NAMESPACES.clear();
  }
}

以下是我的

CustomNamespaces
中的命名空间 HashMap 中存在的命名空间:

{http://ns.namespace1.com/a=a, http://ns.namespace2.com/b=b}

以下是我的编组课程:

final JAXBContext context = final JAXBContext ctx = JAXBContext.newInstance("my classes",Thread.currentThread().getContextClassLoader(),
    new HashMap<>() {
      {
        put(
            JAXBContextProperties.NAMESPACE_PREFIX_MAPPER,
            new StandardNamespaces());
      }
    });
final Marshaller marshaller = context.createMarshaller();; 
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);
marshaller.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, //Trying different method);
marshaller.marshal(o, System.out);

以下是当我传递不同的 Map 或 NamespacePrefixMapper 时得到的不同输出:

  1. 如果我仅将
    StandardNamespaces
    传递给编组器,那么我会得到以下命名空间:
marshaller.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, new StandardNamespaces());

命名空间:

"urn:abc:xyz-query:xsd:2", "abcq",
"http://www.example.org/namespaces/Standard", "sbdh",

这是正确的,但我也想获得自定义名称空间:

{http://ns.namespace1.com/a=a, http://ns.namespace2.com/b=b}
  1. 为了获取自定义和标准名称空间,我尝试了以下操作:
public class CombinedNamespacePrefixMapper extends StandardNamespaces {

  private Map<String, String> namespaceMap;

  public CombinedNamespacePrefixMapper(final Map<String, String> namespaceMap) {
    this.namespaceMap = namespaceMap;
    System.out.println("All Namespaces combined : " + this.namespaceMap);
  }

  @Override
  public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
    System.out.println("URI : " + namespaceUri + " Suggestion : " + suggestion);
    // Check if the namespace URI is present in the map
    String prefix = namespaceMap.get(namespaceUri);
    if (prefix != null) {
      return prefix;
    }
    // Use the default namespace prefix mapper for other namespace URIs
    return super.getPreferredPrefix(namespaceUri, suggestion, requirePrefix);
  }
}

编组过程中通过:

 CombinedNamespacePrefixMapper combinedNamespacePrefixMapper = new CombinedNamespacePrefixMapper(CustomNamespaces.getContext().getAllNamespaces());
marshaller.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, combinedNamespacePrefixMapper);

这只给了我以下标准命名空间:

"urn:abc:xyz-query:xsd:2", "abcq",
"http://www.example.org/namespaces/Standard", "sbdh",

我不确定为什么它会跳过自定义命名空间,即使它们存在于

namespacesMap
中的
CombinedNamespacePrefixMapper
中。

3. 我尝试将它们组合起来并添加如下:

Map<String, String> combinedNamespaceMap = new HashMap<>();
combinedNamespaceMap.putAll(CustomNamespaces.getContext().getAllNamespaces());
combinedNamespaceMap.putAll(StandardNamespaces.NAMESPACE_MAP);

然后将其添加到封送拆收器:

marshaller.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, combinedNamespaceMap);

在这里,我获得了

StandardNamespaces
CustomNamespace
中存在的所有命名空间。

如何仅从我的

StandardNamespaces
映射中获取相关命名空间以及从我的编组 XML 中的
CustomNamespaces
中获取所有命名空间?

我希望我的 XML 最终具有以下命名空间:

{urn:abc:xyz-query:xsd:2=abc,http://www.example.org/namespaces/Standard=sbdh,http://ns.namespace1.com/a=a, http://ns.namespace2.com/b=b}

目前它工作正常,但从 StandardNamespaces 类或 CustomNamespaces 类添加正确的命名空间。有没有办法让它按照 Jakarta Jaxb marshaller 的需要工作?

xml jakarta-ee namespaces jaxb marshalling
1个回答
-1
投票

@BATMAN_2008 你找到解决办法了吗?我还需要一个 Jakarta Jaxb 编组器,但我的 NamespacePrefixMapper 扩展不再工作。
您是否返回到以前的 JAXB 实现

© www.soinside.com 2019 - 2024. All rights reserved.