2016-11-16 14 views
0

У меня есть необычный запрос. Мне нужно создать файл XML, который ищет, например, что-то вроде нижеВключить повторяющиеся пространства имен в элементах xml с помощью java

<?xml version="1.0" encoding="UTF-8"?> 
<pk:DeviceInfo xmlns:pk="urn:ietf:params:xml:ns:kyp:pk" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> 
     <pk:Manufacturer xmlns:pk="urn:ietf:params:xml:ns:kyp:pk" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> 
     ABC 
     </pk:Manufacturer> 
     <pk:SerialNo>123456</pk:SerialNo> 
     <pk:Model>Model1</pk:Model> 
     <pk:IssueNo>1</pk:IssueNo> 
</pk:DeviceInfo> 

Я генерации XML с помощью JDOM API. Проблема в том, что даже если я объявляю пространство имен для элемента pk: Manufacturer, jdom не добавляет его туда, потому что он уже объявлен в корневом элементе. Но мне также нужно повторить объявление пространства имен в дочернем элементе, потому что мне нужно отправить этот файл на другой сервер, для которого требуется, чтобы xml находился в этом формате.
Я верю, что jdom doen't разрешить это, поэтому я попытался создать xml сначала с jdom и обновить xml с помощью парсера dom, чтобы включить пространство имен в дочерний элемент, используя elmt.setAttributeNS(), но, к сожалению, это не кажется работать. Неужели кто-нибудь сталкивался с этой проблемой раньше?

+1

«Мне нужно отправить этот файл на другой сервер, для которого требуется, чтобы xml был в этом формате», говорит о том, что другой сервер не понимает XML с пространствами имен, так как ясно, что любые объявления пространств имен в элементе-предке доступны для потомков, если они не переопределены. Таким образом, объявления внутреннего пространства имен являются избыточными, и большинство сериализаторов DOM-деревьев не будут их выписывать. Обычно нет простого выхода, кроме того, чтобы установить другую сторону, чтобы принять XML или написать собственный сериализатор, который гарантирует, что он выпишет избыточные объявления пространства имен. –

+0

Возможно реализовать собственную настройку «процессора» XMLOutputter, и для этой настройки для печати пространства имен все соответствующие уровни документа. Тем не менее, это было бы последним средством. Было бы лучше исправить систему с другой стороны, чтобы использовать синтаксический анализатор XML для синтаксического анализа содержимого (то, что у вас сейчас явно не соответствует парсеру). Вы захотите реализовать свой собственный процессор и изменить эту строку: https://github.com/hunterhacker/jdom/blob/master/core/src/java/org/jdom2/output/support/AbstractXMLOutputProcessor.java#L805 – rolfl

+0

Вы может попытаться генерировать XML, используя различные URI пространства имен на каждом уровне, а затем выполнить некоторую пост-обработку (используя инструменты, отличные от XML), чтобы заменить фиктивные URI на реальные. (Но, как говорили другие, если приложение не читает или пишет XML правильно, вы действительно не хотите, чтобы его недостатки проникали наружу в другие части системы: вы должны исправить сломанное приложение). –

ответ

1

Вы не показали нам, какие DOM код, который вы пытались, но когда я проверить

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
    dbf.setNamespaceAware(true); 

    DocumentBuilder db = dbf.newDocumentBuilder(); 

    Document doc = db.newDocument(); 

    String ns1 = "http://example.com/ns1"; 
    String ns2 = "http://example.com/ns2"; 

    Element root = doc.createElementNS(ns1, "pf1:root"); 
    root.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:pf2", ns2); 

    doc.appendChild(root); 

    Element foo = doc.createElementNS(ns1, "pf1:foo"); 
    foo.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:pf1", ns1); 
    foo.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:pf2", ns2); 
    root.appendChild(foo); 

    DOMImplementationLS domImp = (DOMImplementationLS)doc.getImplementation(); 

    LSSerializer ser = domImp.createLSSerializer(); 

    System.out.println(ser.writeToString(doc)); 

с Oracle Java 1.8 выход

<pf1:root xmlns:pf1="http://example.com/ns1" xmlns:pf2="http://example.com/ns2"><pf1:foo xmlns:pf1="http://example.com/ns1" xmlns:pf2="http://example.com/ns2"/></pf1:root> 

, таким образом, явно созданных объявлений атрибутов пространства имен на ребенка сериализованы. Таким образом, это должен быть способ для W3C DOM, явно создавать объявления пространств имен для элементов, которые вам нужны, и использовать LSSerializer для выписывания дерева.

+0

Отлично! LSSerializer сделал трюк для меня. Раньше я использовал javax.xml.transform.Transformer для преобразования источника dom в xml. Теперь LSSerializer может писать xml с повторяющимися пространствами имен. –