如何从生成的JAXB中删除命名空间

时间:2014-04-01 03:13:10

标签: java xml jaxb xsd xjc

使用JAVA 7,XJC。

xsd由使用.NET的第三方提供。

当前的问题是,当我将对象编组为XML时,我会得到以下几点:

<SalesOrder xmlns:ns2="http://schemas.datacontract.org/2004/07/RKLServiceQueue">
  <ns2:BillToAddrLine1>7315 N Ritter Ave</ns2:BillToAddrLine1>
  <ns2:BillToAddrLine2></ns2:BillToAddrLine2>
  <ns2:BillToAddrName>David Kruse</ns2:BillToAddrName>
  <ns2:BillToCity>Indianapolis</ns2:BillToCity>
  <ns2:BillToCountryID>USA</ns2:BillToCountryID>
  <ns2:BillToPostalCode>46250</ns2:BillToPostalCode>
</SalesOrder

该服务期待这样的事情:

  <SalesOrder xmlns="http://schemas.datacontract.org/2004/07/RKLServiceQueue">
    <BillToAddrLine1>String content</BillToAddrLine1>
    BillToAddrLine2>String content</BillToAddrLine2>
    <BillToAddrLine3>String content</BillToAddrLine3>
    <BillToAddrLine4>String content</BillToAddrLine4>
    <BillToAddrLine5>String content</BillToAddrLine5>
    <BillToAddrName>String content</BillToAddrName>
    <BillToCity>String content</BillToCity>
  </SalesOrder>

这也是xsd的一部分

<xs:schema xmlns:tns="http://schemas.datacontract.org/2004/07/RKLServiceQueue" elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/RKLServiceQueue" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:complexType name="SalesOrder">
    <xs:sequence>
      <xs:element minOccurs="0" name="BillToAddrLine1" nillable="true" type="xs:string" />
      <xs:element minOccurs="0" name="BillToAddrLine2" nillable="true" type="xs:string" />
      <xs:element minOccurs="0" name="BillToAddrLine3" nillable="true" type="xs:string" />
      <xs:element minOccurs="0" name="BillToAddrLine4" nillable="true" type="xs:string" />
      <xs:element minOccurs="0" name="BillToAddrLine5" nillable="true" type="xs:string" />
      <xs:element minOccurs="0" name="BillToAddrName" nillable="true" type="xs:string" />
      <xs:element minOccurs="0" name="BillToCity" nillable="true" type="xs:string" />
      <xs:element minOccurs="0" name="BillToCountryID" nillable="true" type="xs:string" />
      <xs:element minOccurs="0" name="BillToPostalCode" nillable="true" type="xs:string" />
      <xs:element minOccurs="0" name="BillToStateID" nillable="true" type="xs:string" />

我已经对SoapUI进行了测试以验证。

我在网上做了一些搜索,包括stackoverflow,它指向使用NamespacePrefixMapper,但似乎没有做到这一点。我一直得到以下例外:

javax.xml.bind.PropertyException: name: com.sun.xml.internal.bind.marshaller.namespacePrefixMapper value: com.heritage.jobs.MyPrefixMapper@29545330 

这是映射器

import com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper;


/**
 * 
 */
public class MyPrefixMapper extends NamespacePrefixMapper
{
    private static final String FOO_PREFIX = ""; // DEFAULT NAMESPACE
    private static final String FOO_URI = "http://schemas.datacontract.org/2004/07/RKLServiceQueue";


    /*
     * (non-Javadoc)
     * 
     * @see com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper#getPreferredPrefix(java.lang.String,
     * java.lang.String, boolean)
     */
    @Override
    public String getPreferredPrefix(final String pNameSpaceUri, final String pSuggestion, final boolean pRequirePrefix)
    {
        if (FOO_URI.equals(pNameSpaceUri))
        {
            return FOO_PREFIX;
        }

        return pSuggestion;
    }

以下是我用它来称呼它:

final JAXBContext context = JAXBContext.newInstance(SalesOrder.class);

marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");

final MyPrefixMapper prefixMapper = new MyPrefixMapper();
try
{
        marshaller.setProperty("com.sun.xml.internal.bind.marshaller.namespacePrefixMapper", prefixMapper);
}
catch (final PropertyException e)
{
LOG.error("perform(CronJobModel)", e);
}

我不清楚我缺少什么才能使这项工作 - 如何从每个字段/属性中删除命名空间ns?

3 个答案:

答案 0 :(得分:1)

尝试使用package-info.java中的注释,如下所示:

@javax.xml.bind.annotation.XmlSchema(namespace = "http://myOutput", xmlns = {@XmlNs(prefix = "", namespaceURI = "http://myOutput")}, elementFormDefault = XmlNsForm.QUALIFIED)

这样我就摆脱了根元素上的ns2 ......

答案 1 :(得分:0)

尝试删除internalimport中的property,如下所示:

import com.sun.xml.bind.marshaller.NamespacePrefixMapper;

......和,

marshaller.setProperty("com.sun.xml.bind.marshaller.namespacePrefixMapper", prefixMapper);

答案 2 :(得分:0)

您可以使用以下代码:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.newDocument();

JAXBContext context = JAXBContext.newInstance(RequestXml.class);
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(new RequestXml(), document);

new NamespaceRemover().remove(document);

StringWriter writer = new StringWriter();
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(writer));

System.out.println(writer.toString());

NamespaceRemover的实现方式如下:

public class NamespaceRemover {

    public void remove(Node node) {
        Document doc = node.getOwnerDocument();

        String localName = tryToResolveLocalName(node.getNodeName());
        if (localName != null)
            doc.renameNode(node, null, localName);

        NamedNodeMap attributes = node.getAttributes();
        if (attributes != null)
            remove(attributes);

        remove(node.getChildNodes());
    }

    protected String tryToResolveLocalName(String nodeName) {
        if (nodeName == null || nodeName.startsWith("#"))
            return null;

        String[] tagParts = nodeName.split(":");
        return tagParts[tagParts.length - 1];
    }

    public void remove(NodeList childNodes) {
        for (int i = 0; i < childNodes.getLength(); i++)
            remove(childNodes.item(i));
    }

    public void remove(NamedNodeMap attributes) {
        List<String> attrsToBeRemoved = new ArrayList<>();

        for (int i = 0; i < attributes.getLength(); i++) {
            Node attr = attributes.item(i);
            if (attr.getNodeName().startsWith("xmlns:") || "xmlns".equals(attr.getNodeName()))
                attrsToBeRemoved.add(attr.getNodeName());
            else
                remove(attributes.item(i));
        }

        for (String attrToBeRemoved : attrsToBeRemoved)
            attributes.removeNamedItem(attrToBeRemoved);
    }

}

NamespaceRemover也可用于从XML文档的子树中删除名称空间。