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

How to combine and include namespaces from a custom `NamespacePrefixMapper` and a `HashMap` during Jakarta JAX-B marshalling,

提问人:BATMAN_2008 提问时间:3/21/2023 更新时间:11/21/2023 访问量:183

问:

我正在尝试使用 the 封送一个 Java 对象,除了在生成的 XML 中包含命名空间外,一切都运行良好。Jakarta JAXB marshaller

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

以下是我的: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);
  }
}

以下是我的,其中包含一个带有命名空间的 HashMap:CustomNamespaces.class

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();
  }
}

以下是我的命名空间中存在的命名空间 HashMap 存在于我的 :CustomNamespaces

{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",

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

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

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

然后将其添加到封送程序中:

marshaller.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, combinedNamespaceMap);

在这里,我得到了 和 中存在的所有命名空间。StandardNamespacesCustomNamespace

如何仅从映射中获取相关命名空间,并从编组的 XML 中获取所有命名空间?StandardNamespacesCustomNamespaces

我希望我的 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 类添加正确的命名空间。有没有办法让它按照我需要的雅加达 Jaxb 编组工作?

XML Jakarta-EE 名称空间 JAXB 编组

评论


答: 暂无答案