我正在尝试使用
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 时得到的不同输出:
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}
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 的需要工作?
@BATMAN_2008 你找到解决办法了吗?我还需要一个 Jakarta Jaxb 编组器,但我的 NamespacePrefixMapper 扩展不再工作。
您是否返回到以前的 JAXB 实现