2009-03-10 9 views
7

Se ho un documento XML comeCome estrarre l'elemento figlio da XML in una stringa in Java?

<root> 
    <element1> 
     <child attr1="blah"> 
      <child2>blahblah</child2> 
     <child> 
    </element1> 
</root> 

Voglio ottenere una stringa XML con il primo elemento figlio. La mia stringa di output sarebbe

<element1> 
    <child attr1="blah"> 
     <child2>blahblah</child2> 
    <child> 
</element1> 

Ci sono molti approcci, vorrei vedere alcune idee. Ho cercato di utilizzare le API Java XML per questo, ma non è chiaro che ci sia un buon modo per farlo.

grazie

risposta

7

Hai ragione, con l'API XML standard, non c'è un buon modo - ecco un esempio (può essere bug cavalcato, ma corre, ma ho scritto molto tempo fa).

import javax.xml.*; 
import javax.xml.parsers.*; 
import javax.xml.transform.*; 
import javax.xml.transform.dom.*; 
import javax.xml.transform.stream.*; 
import org.w3c.dom.*; 
import java.io.*; 

public class Proc 
{ 
    public static void main(String[] args) throws Exception 
    { 
     //Parse the input document 
     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder builder = factory.newDocumentBuilder(); 
     Document doc = builder.parse(new File("in.xml")); 

     //Set up the transformer to write the output string 
     TransformerFactory tFactory = TransformerFactory.newInstance(); 
     Transformer transformer = tFactory.newTransformer(); 
     transformer.setOutputProperty("indent", "yes"); 
     StringWriter sw = new StringWriter(); 
     StreamResult result = new StreamResult(sw); 

     //Find the first child node - this could be done with xpath as well 
     NodeList nl = doc.getDocumentElement().getChildNodes(); 
     DOMSource source = null; 
     for(int x = 0;x < nl.getLength();x++) 
     { 
      Node e = nl.item(x); 
      if(e instanceof Element) 
      { 
       source = new DOMSource(e); 
       break; 
      } 
     } 

     //Do the transformation and output 
     transformer.transform(source, result); 
     System.out.println(sw.toString()); 
    } 
} 

Sembrerebbe come si potrebbe ottenere il primo figlio semplicemente utilizzando doc.getDocumentElement(). GetFirstChild(), ma il problema è che se c'è qualche spazio tra la radice e l'elemento secondario, che creerà un nodo di testo nell'albero e otterrai quel nodo invece del nodo di elemento reale. L'output di questo programma è:

D:\home\tmp\xml>java Proc 
<?xml version="1.0" encoding="UTF-8"?> 
<element1> 
     <child attr1="blah"> 
      <child2>blahblah</child2> 
     </child> 
    </element1> 

Penso che si può sopprimere la stringa xml version se non ne hai bisogno, ma non sono sicuro su questo. Probabilmente cercherò di utilizzare una libreria XML di terze parti se possibile.

3

mi sento di raccomandare JDOM. È una libreria XML Java che rende molto più semplice gestire XML con l'approccio W3C standard.

1

XMLBeans è uno strumento facile da usare (una volta capito) per gestire XML senza dover affrontare i fastidi del parsing.

È necessario disporre di uno schema per il file XML, ma fornisce anche uno strumento per generare uno schema da un file XML exisint (a seconda delle esigenze, è probabile che il generato sia corretto).

5

Dal momento che questa è la risposta di Google in alto e per quelli di voi che vogliono solo la base:

public static String serializeXml(Element element) throws Exception 
{ 
    ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 
    StreamResult result = new StreamResult(buffer); 

    DOMSource source = new DOMSource(element); 
    TransformerFactory.newInstance().newTransformer().transform(source, result); 

    return new String(buffer.toByteArray()); 
} 

Io lo uso per il debug, che molto probabilmente è quello che serve questo per

+0

Sai come impedire al trasformatore di aggiungere ? – jophde

0

Come domanda è in realtà circa prima occorrenza della stringa all'interno di un'altra stringa, userei metodi della classe String, invece di parser XML:

public static String getElementAsString(String xml, String tagName){ 
    int beginIndex = xml.indexOf("<" + tagName); 
    int endIndex = xml.indexOf("</" + tagName, beginIndex) + tagName.length() + 3; 
    return xml.substring(beginIndex, endIndex); 
} 
0
public String getXML(String xmlContent, String tagName){ 

    String startTag = "<"+ tagName + ">"; 
    String endTag = "</"+ tagName + ">"; 
    int startposition = xmlContent.indexOf(startTag); 
    int endposition = xmlContent.indexOf(endTag, startposition); 
    if (startposition == -1){ 
     return "ddd"; 
    } 
    startposition += startTag.length(); 
    if(endposition == -1){ 
     return "eee"; 
    } 
    return xmlContent.substring(startposition, endposition); 
} 

Passa il tuo xml come stringa a questo metodo, e nel tuo caso passa 'elemento' come parametro tagname.

0

È possibile utilizzare seguente funzione per estrarre blocco xml come stringa passando corretta un'espressione XPath,

private static String nodeToString(Node node) throws TransformerException 
{ 
    StringWriter buf = new StringWriter(); 
    Transformer xform = TransformerFactory.newInstance().newTransformer(); 
    xform.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 
    xform.transform(new DOMSource(node), new StreamResult(buf)); 
    return(buf.toString()); 
} 

    public static void main(String[] args) throws Exception 
{ 
     DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); 
     Document doc = dBuilder.parse(inputFile); 

     XPath xPath = XPathFactory.newInstance().newXPath(); 
     Node result = (Node)xPath.evaluate("A/B/C", doc, XPathConstants.NODE); //"A/B[id = '1']" //"//*[@type='t1']" 

     System.out.println(nodeToString(result)); 

}