2012-06-21 13 views
5

Tworzę obiekt dokumentu W3C, używając wartości typu String. Po utworzeniu obiektu Document, chcę dodać obszar nazw do głównego elementu tego dokumentu. Oto mój bieżący kod:Dodawanie obszaru nazw do już utworzonego dokumentu XML

Document document = builder.parse(new InputSource(new StringReader(xmlString))); 
document.getDocumentElement().setAttributeNS("http://com", "xmlns:ns2", "Test"); 
document.setPrefix("ns2"); 
TransformerFactory tranFactory = TransformerFactory.newInstance(); 
Transformer aTransformer = tranFactory.newTransformer(); 
Source src = new DOMSource(document); 
Result dest = new StreamResult(new File("c:\\xmlFileName.xml")); 
aTransformer.transform(src, dest); 

Co mogę używać jako wejście:

<product> 
    <arg0>DDDDDD</arg0> 
    <arg1>DDDD</arg1> 
</product> 

Co wyjście powinno wyglądać następująco:

<ns2:product xmlns:ns2="http://com"> 
    <arg0>DDDDDD</arg0> 
    <arg1>DDDD</arg1> 
</ns2:product> 

trzeba dodać wartość prefiksu i nazw również wejściowy ciąg xml. Jeśli spróbuję powyższego kodu, otrzymuję ten wyjątek:

NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces. 

Doceń swoją pomoc!

+1

Is Twój 'builder' przestrzenie nazw? 'builder.isNamespaceAware()' – rolve

Odpowiedz

19

Ponieważ nie istnieje łatwy sposób na zmianę nazwy elementu głównego, musimy zastąpić go elementem, który ma prawidłową przestrzeń nazw i atrybut, a następnie skopiować do niego wszystkie oryginalne elementy potomne. Wymuszenie deklaracji przestrzeni nazw nie jest potrzebne, ponieważ poprzez nadanie elementowi poprawnego obszaru nazw (URI) i ustawienie prefiksu, deklaracja będzie automatyczna.

Wymienić setAttribute i setPrefix z tej linii (2,3)

String namespace = "http://com"; 
String prefix = "ns2"; 
// Upgrade the DOM level 1 to level 2 with the correct namespace 
Element originalDocumentElement = document.getDocumentElement(); 
Element newDocumentElement = document.createElementNS(namespace, originalDocumentElement.getNodeName()); 
// Set the desired namespace and prefix 
newDocumentElement.setPrefix(prefix); 
// Copy all children 
NodeList list = originalDocumentElement.getChildNodes(); 
while(list.getLength()!=0) { 
    newDocumentElement.appendChild(list.item(0)); 
} 
// Replace the original element 
document.replaceChild(newDocumentElement, originalDocumentElement); 

w oryginalnym kodzie podjęto próbę zadeklarować elementu nazw tak:

.setAttributeNS("http://com", "xmlns:ns2", "Test"); 

pierwszy parametr przestrzeń nazw atrybutu, a ponieważ jest to atrybut przestrzeni nazw, musi mieć identyfikator URI http://www.w3.org/2000/xmlns/. Deklarowana nazw powinna przyjść na 3rd parametru

.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:ns2", "http://com"); 
+0

Wielkie dzięki! Naprawdę mi pomogło, w moim przypadku przestrzeń nazw nigdy nie została uwzględniona w obliczeniach trawienia, ponieważ dodałem ją jako zwykły atrybut zamiast dodawać go jako rzeczywisty obszar nazw. +1 – Springrbua

+0

Wygląda na to, że to podejście nie może dodać tej samej przestrzeni nazw do elementu potomnego, więc używam tego podejścia, następnie generuję łańcuch XML z dokumentu i ponownie analizuję wygenerowany łańcuch XML. – wangf

0

podejście Bellow pracuje również dla mnie, ale prawdopodobnie nie powinno się używać w przypadku wydajności krytycznej.

  1. Dodaj przestrzeń nazw do dokumentu głównego elementu jako atrybutu.
  2. Przekształć dokument w ciąg znaków XML. Celem tego kroku jest sprawienie, aby element podrzędny w łańcuchu XML dziedziczył obszar nazw elementu nadrzędnego.
  3. Teraz łańcuch xml ma przestrzeń nazw.
  4. Można użyć ciąg XML do budowy dokument ponownie lub wykorzystywane do JAXB unmarshal itd

private static String addNamespaceToXml(InputStream in) 
     throws ParserConfigurationException, SAXException, IOException, 
     TransformerException { 
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
    /* 
    * Must not namespace aware, otherwise the generated XML string will 
    * have wrong namespace 
    */ 
    // dbf.setNamespaceAware(true); 
    DocumentBuilder db = dbf.newDocumentBuilder(); 
    Document document = db.parse(in); 
    Element documentElement = document.getDocumentElement(); 
    // Add name space to root element as attribute 
    documentElement.setAttribute("xmlns", "http://you_name_space"); 
    String xml = transformXmlNodeToXmlString(documentElement); 
    return xml; 
} 

private static String transformXmlNodeToXmlString(Node node) 
     throws TransformerException { 
    TransformerFactory transFactory = TransformerFactory.newInstance(); 
    Transformer transformer = transFactory.newTransformer(); 
    StringWriter buffer = new StringWriter(); 
    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 
    transformer.transform(new DOMSource(node), new StreamResult(buffer)); 
    String xml = buffer.toString(); 
    return xml; 
} 
Powiązane problemy