Как удалить пространство имен из сгенерированного JAXB
Используя 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, чтобы проверить.
Я провел небольшой поиск в Интернете, включая stackru, и он указывает на использование 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 из каждого из полей / свойств?
2 ответа
Вы можете использовать следующий код:
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-документа.
Попробуйте использовать аннотации в package-info.java следующим образом:
@javax.xml.bind.annotation.XmlSchema(namespace = "http://myOutput", xmlns = {@XmlNs(prefix = "", namespaceURI = "http://myOutput")}, elementFormDefault = XmlNsForm.QUALIFIED)
Таким образом я избавился от ns2 на корневом элементе...
Попробуйте удалить internal
в import
И в property
как это:
import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
... а также,
marshaller.setProperty("com.sun.xml.bind.marshaller.namespacePrefixMapper", prefixMapper);