-1

我正在使用JaxB Marshalling来创建XML. 我的 XML 我使用该JAXB XmlAdapter选项创建的自定义字段很少。自定义字段是使用JAXBElement, 其中QName参数之一创建的。

根据QName文档,它需要 3 个参数NamespaceURILocalPart并且Prefix. 我正在传递所有这些参数。但由于某种原因,createdXML采用默认命名空间前缀ns0, ns1, ns2等,而不是在QName创建参数中提供的前缀。

一切都按预期工作,没有任何问题。我只想知道如何使我作为参数传递QName的值而不是它自动添加的值。我知道,如果我不传递该值,那么它将采用,但在我的情况下,即使在传递了该值之后,它也会分配我想要避免的值。我尝试了很多东西,但仍然没有成功。custom prefixdefault namespace prefixprefixdefault namespace prefixcustom prefixdefault namespaces prefixXML

注意:我没有使用javax Jaxblibraray,而是使用EclipseLink Moxy基于Jaxb实现的libraray。

目前,创建的 XML 看起来像这样:(请注意,这些不是根元素或 XML 标头,而是从 XML 的某个部分获取的块)。

   <ns0:MainField xmlns:ns0="https://google.com?xsd=google.xsd">
      <ns1:SubField1 xmlns:ns1="https://fb.com?xsd=fb.xsd">
         <ns2:Field1 xmlns:ns2="https://fb.com?xsd=fb.xsd">Value1</ns2:Field1>
      </ns1:SubField1>
      <ns3:SubField3 xmlns:ns3="https://google.com?xsd=google.xsd">SubValue3</ns3:SubField3>
   </ns0:MainField>
   <ns4:MainField2 xmlns:ns4="https://google.com?xsd=google.xsd">MainValue2</ns4:MainField2>

QName根据我提供给该字段的值,我期望它看起来像这样:

   <google:MainField xmlns:google="https://google.com?xsd=google.xsd">
      <fb:SubField1 xmlns:fb="https://fb.com?xsd=fb.xsd">
         <fb:Field1 xmlns:fb="https://fb.com?xsd=fb.xsd">Value1</fb:Field1>
      </fb:SubField1>
      <google:SubField3 xmlns:google="https://google.com?xsd=google.xsd">SubValue3</google:SubField3>
   </google:MainField>
   <google:MainField2 xmlns:google="https://google.com?xsd=google.xsd">MainValue2</google:MainField2>

以下是我的Java课程,它正在创建QName. 我有一个Map<String, Object>基于它创建的值的类型QName。一切都按预期工作,除了QName namespace prefix.

import io.openepcis.service.jaxb.DefaultJsonSchemaNamespaceURIResolver;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.annotation.XmlAnyElement;
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.xml.namespace.QName;
import org.apache.commons.lang3.NotImplementedException;


public class MapAdapter extends XmlAdapter<MapWrapper, Map<String, Object>> {

  DefaultJsonSchemaNamespaceURIResolver uriResolver = new DefaultJsonSchemaNamespaceURIResolver();

  @Override
  public Map<String, Object> unmarshal(MapWrapper valueType) throws Exception {
    throw new NotImplementedException();
  }

  @Override
  public MapWrapper marshal(Map<String, Object> extensions) throws Exception {
    if (extensions == null) {
      return null;
    }

    MapWrapper wrapper = new MapWrapper();

    List elements = new ArrayList();

    //Loop through the Extensions MAP
    for (Map.Entry<String, Object> property : extensions.entrySet()) {
    

        final Optional<String> xmlNamespace = uriResolver.namespaceURIFromSchema(extension.getKey());
        
        String namespaceURI = xmlNamespace.get();
        String localPart = getLocalPart(property.getKey());
        String prefix = getPrefix(property.getKey());
        String label = getCleanLabel(property.getKey());
        System.out.println(" namespaceURI : " + namespaceURI + " localPart : " + localPart + " prefix : " + prefix);
        
        //If the Value type is MAP then recurse through the loop
        if (property.getValue() instanceof Map) {
        elements.add(new JAXBElement<MapWrapper>(new QName(namespaceURI, localPart, prefix), MapWrapper.class, marshal((Map) property.getValue())));
        } else if (property.getValue() instanceof String) {
        // If the Value type is String then directly create JAXBElement
        elements.add(new JAXBElement<String>(new QName(namespaceURI, localPart, prefix), String.class, property.getValue().toString()));
        }
        }
        wrapper.elements = elements;
        return wrapper;
    }
  
    // Formats the complete Label for the XML tag
    public static String getCleanLabel(String label) {
        label = label.replaceAll("[()]", "").replaceAll("[^\\w\\s]", "_").replaceAll(" ", "_");
        return label;
    }
    
    //Formats the LocalPart of the XML Tag (after ":")
    public static String getLocalPart(String localPart) {
        localPart = localPart.substring(localPart.indexOf(":") + 1);
        return localPart;
    }
    
    //Formats the Prefix of the XML Tag (before ":")
    public static String getPrefix(String prefix) {
        prefix = prefix.substring(0, prefix.indexOf(":"));
        return prefix;
    }
}

class MapWrapper {
  @XmlAnyElement
  List elements;
}


class DefaultJsonSchemaNamespaceURIResolver{
    private static Map<String, String> xmlNamespaces = new HashMap<String, String>();
    
    static {
        xmlNamespaces.put("google", "https://google.com");
        xmlNamespaces.put("fb", "https://fb.com");
        xmlNamespaces.put("insta", "https://instagram.com");
    }
    
    public Optional<String> namespaceURIFromSchema(String schemaURI) {
        if (xmlNamespaces.containsKey(schemaURI)) {
          return Optional.of(xmlNamespaces.get(schemaURI));
        }
        return Optional.empty();
    }
}


以下是我在我的使用的依赖项Maven pom.xml

    <!-- JAXB Annotations Dependencies START -->

    <dependency>
      <groupId>jakarta.xml.bind</groupId>
      <artifactId>jakarta.xml.bind-api</artifactId>
      <version>3.0.1</version>
    </dependency>

    <dependency>
      <groupId>org.eclipse.persistence</groupId>
      <artifactId>eclipselink</artifactId>
      <version>3.0.0</version>
    </dependency>

    <!-- JAXB Annotations Dependencies END -->
4

1 回答 1

0

在尝试了很多事情并参考了很多事情之后,我能够得到它。我使用的是Moxy依赖项,而不是Jaxb因为它在Jaxb. 发布此答案,因为它可能对将来的某人有所帮助:

  1. 删除它package-info.java及其所有内容(如果您在尝试某些内容时添加了它,因为我在这里看到很多答案都是基于它的)。

  2. 由于您使用的是 ,因此Moxy您可以创建一个包含所有必需的 MapNamespcaeURIPrefix. 像这样的东西:

    Map<String, String> urisToPrefixes = new HashMap<String, String>();
    urisToPrefixes.put("http://www.root.com", "rootNS");
    urisToPrefixes.put("http://sub.root.com", "subNS"); 
  1. 在使用编组方法时,添加属性并将此 Map 作为参数发送:
marshaller.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, urisToPrefixes);

这将确保每当Namespace遇到 a 时,它都会检查相应的prefix并将其添加到 XML 标头中,因此它会将所有默认前缀 ns0、ns1 等替换为映射中的相应前缀。

JAXBContext ctx = JAXBContext.newInstance(new Class[] { TestObject.class, SubObject.class });
 
Map<String, String> urisToPrefixes = new HashMap<String, String>();
urisToPrefixes.put("http://www.root.com", "rootNS");
urisToPrefixes.put("http://sub.root.com", "subNS");        
 
Marshaller m = ctx.createMarshaller();
m.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, prefixesToUris);

如果您想了解更多关于它的信息,请点击此处的官方文档

于 2021-05-17T08:28:59.420 回答