Bir dizede XML'den org.w3c.dom.Document'ı nasıl yüklerim?


103

Bir dizede tam bir XML belgem var ve bir Documentnesne istiyorum . Google her türlü çöpü ortaya çıkarır. En basit çözüm nedir? (Java 1.5'te)

Çözüm Matt McMinn sayesinde , bu uygulamaya karar verdim. Benim için doğru düzeyde giriş esnekliğine ve olağanüstü ayrıntı düzeyine sahip. (Hatanın hatalı biçimlendirilmiş XML'den gelip gelmediğini bilmekte fayda var -SAXException - yoksa kötü GÇ'den miIOException .)

public static org.w3c.dom.Document loadXMLFrom(String xml)
    throws org.xml.sax.SAXException, java.io.IOException {
    return loadXMLFrom(new java.io.ByteArrayInputStream(xml.getBytes()));
}

public static org.w3c.dom.Document loadXMLFrom(java.io.InputStream is) 
    throws org.xml.sax.SAXException, java.io.IOException {
    javax.xml.parsers.DocumentBuilderFactory factory =
        javax.xml.parsers.DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true);
    javax.xml.parsers.DocumentBuilder builder = null;
    try {
        builder = factory.newDocumentBuilder();
    }
    catch (javax.xml.parsers.ParserConfigurationException ex) {
    }  
    org.w3c.dom.Document doc = builder.parse(is);
    is.close();
    return doc;
}

Çözümü düzeltebilirsen çok iyi olur. String.getByptes ve InputStream kullanmak i18n problemlerini ortaya çıkarır. Arkadaşımdan biri kodu buradan aldı, bu da yanlış. Findbugs sorunu tespit ettiği için şanslı. Erickson tarafından sağlanan doğru çözüm, InputSource'u kullanmaktır.
Kenneth Xu

Yanıtlar:


80

Bu benim için Java 1.5'te çalışıyor - Okunabilirlik için belirli istisnaları kaldırdım.

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import java.io.ByteArrayInputStream;

public Document loadXMLFromString(String xml) throws Exception
{
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

    factory.setNamespaceAware(true);
    DocumentBuilder builder = factory.newDocumentBuilder();

    return builder.parse(new ByteArrayInputStream(xml.getBytes()));
}

28
Sylvarking'in cevabında belirtildiği gibi, bu kod, getBytes()kodlamayı dikkate almadan kullanır .
McDowell

2
Ericson'ın cevabını mı kastediyorsun? veya belki profilini yeniden adlandırdı?
rogerdpack

1
döküm olmamalı mı return (Document) builder.parse(new ByteArrayInputStream(xml.getBytes()));??
InfantPro'Aravind '16

150

Vay canına!

Bu kodla ilgili potansiyel olarak ciddi bir sorun var, çünkü içinde belirtilen karakter kodlamasını yok sayıyor String(varsayılan olarak UTF-8'dir). Aradığın zamanString.getBytes()Platform varsayılan kodlaması , Unicode karakterlerini baytlara kodlamak için kullanılır. Bu nedenle, ayrıştırıcı, aslında EBCDIC veya başka bir şey alırken UTF-8 verisi aldığını düşünebilir ...

Bunun yerine, aşağıdaki gibi bir Okuyucu ile oluşturulabilen bir InputSource alan ayrıştırma yöntemini kullanın:

import java.io.StringReader;
import org.xml.sax.InputSource;

        return builder.parse(new InputSource(new StringReader(xml)));

Büyük bir sorun gibi görünmeyebilir, ancak karakter kodlama sorunlarının cehaleti, y2k'ye benzer sinsi kod çürümesine yol açar.


3
Google'da çok basit ama çok zor bir çözüm. Teşekkür ederim +1
pat8719

6
Şimdi, kabul edilen cevabı kopyalayıp yapıştırmakla kalmamam, bunun yerine okumam gerektiğini anlıyorum.
Vitaly Sazanovich

1
Harika! Aşağıdaki kurulum dosyasıyla JDK8'de hayatlarımızı kurtardı. Kodlama = ISO-8859_1, javax.servlet.request.encoding = UTF-8 PS Doğru olarak etiketlenen yanıt bizim için işe yaramadı
kosta5

9

Dokümana değil de bir NodeList'e ihtiyacım olması dışında benzer bir problem yaşadım, işte bulduğum şey. Çoğunlukla daha önce olduğu gibi aynı çözüm, kök öğeyi bir NodeList olarak almak ve erickson'ın karakter kodlama sorunları yerine bir InputSource kullanma önerisini kullanmak için artırıldı.

private String DOC_ROOT="root";
String xml=getXmlString();
Document xmlDoc=loadXMLFrom(xml);
Element template=xmlDoc.getDocumentElement();
NodeList nodes=xmlDoc.getElementsByTagName(DOC_ROOT);

public static Document loadXMLFrom(String xml) throws Exception {
        InputSource is= new InputSource(new StringReader(xml));
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        DocumentBuilder builder = null;
        builder = factory.newDocumentBuilder();
        Document doc = builder.parse(is);
        return doc;
    }

1

Java'da XML'i işlemek için her zaman Transformer API'yi kullanma eğilimindeyim:

import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamSource;

public static Document loadXMLFrom(String xml) throws TransformerException {
    Source source = new StreamSource(new StringReader(xml));
    DOMResult result = new DOMResult();
    TransformerFactory.newInstance().newTransformer().transform(source , result);
    return (Document) result.getNode();
}   
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.