Domanda

Ho un XmlDocument in Java, creato con il Weblogic XmlDocument parser.

Voglio sostituire il contenuto di un tag in this XMLDocument con i miei dati, oppure inserisci il tag se non c'è.

<customdata>
   <tag1 />
   <tag2>mfkdslmlfkm</tag2>
   <location />
   <tag3 />
</customdata>

Ad esempio, voglio inserire un URL nel tag location:

<location>http://something</location>

ma per il resto lascia l'XML così com'è.

Attualmente utilizzo a XMLCursor:

    XmlObject xmlobj = XmlObject.Factory.parse(a.getCustomData(), options);
    XmlCursor xmlcur = xmlobj.newCursor();

    while (xmlcur.hasNextToken()) {
      boolean found = false;
      if (xmlcur.isStart() && "schema-location".equals(xmlcur.getName().toString())) {
        xmlcur.setTextValue("http://replaced");
        System.out.println("replaced");
        found = true;
      } else if (xmlcur.isStart() && "customdata".equals(xmlcur.getName().toString())) {
        xmlcur.push();
      } else if (xmlcur.isEnddoc()) {
        if (!found) {
          xmlcur.pop();
          xmlcur.toEndToken();
          xmlcur.insertElementWithText("schema-location", "http://inserted");
          System.out.println("inserted");
        }

      }
      xmlcur.toNextToken();
    }

Ho provato a trovare un "veloce" xquery modo per farlo dal momento che XmlDocument ha un execQuery metodo, ma non l'ho trovato molto semplice.

Qualcuno ha un modo migliore di questo?Sembra un po' elaborato.

È stato utile?

Soluzione

Che ne dici di un approccio basato su XPath?Mi piace questo approccio perché la logica è semplicissima da capire.Il codice è praticamente autodocumentante.

Se il tuo documento xml è disponibile come oggetto org.w3c.dom.Document (come ritorna la maggior parte dei parser), allora potresti fare qualcosa di simile a quanto segue:

// get the list of customdata nodes
NodeList customDataNodeSet = findNodes(document, "//customdata" );

for (int i=0 ; i < customDataNodeSet.getLength() ; i++) {
  Node customDataNode = customDataNodeSet.item( i );

  // get the location nodes (if any) within this one customdata node
  NodeList locationNodeSet = findNodes(customDataNode, "location" );

  if (locationNodeSet.getLength() > 0) {
    // replace
    locationNodeSet.item( 0 ).setTextContent( "http://stackoverflow.com/" );
  }
  else {
    // insert
    Element newLocationNode = document.createElement( "location" );
    newLocationNode.setTextContent("http://stackoverflow.com/" );
    customDataNode.appendChild( newLocationNode );
  }
}

Ed ecco il metodo di supporto findNodes che esegue la ricerca XPath.

private NodeList findNodes( Object obj, String xPathString )
  throws XPathExpressionException {

  XPath xPath = XPathFactory.newInstance().newXPath();
  XPathExpression expression = xPath.compile( xPathString );
  return (NodeList) expression.evaluate( obj, XPathConstants.NODESET );
}

Altri suggerimenti

Che ne dici di un approccio orientato agli oggetti?È possibile deserializzare l'XML in un oggetto, impostare il valore della posizione sull'oggetto, quindi serializzare nuovamente in XML.

XStream lo rende davvero facile.

Ad esempio, definiresti l'oggetto principale, che nel tuo caso è CustomData (sto utilizzando i campi pubblici per mantenere semplice l'esempio):

public class CustomData {
  public String tag1;
  public String tag2;
  public String location;
  public String tag3;
}

Quindi inizializzi XStream:

XStream xstream = new XStream();
// if you need to output the main tag in lowercase, use the following line
xstream.alias("customdata", CustomData.class);  

Ora puoi costruire un oggetto da XML, impostare il campo location sull'oggetto e rigenerare l'XML:

CustomData d = (CustomData)xstream.fromXML(xml);
d.location = "http://stackoverflow.com";
xml = xstream.toXML(d);

Come ti sembra?

Se non conosci lo schema, la soluzione XStream probabilmente non è la strada da percorrere.Almeno XStream è sul tuo radar adesso, potrebbe tornare utile in futuro!

Dovresti essere in grado di farlo con query

Tentativo

 fn:replace(string,pattern,replace)

Sono nuovo a xquery e ho trovato che sia un linguaggio di query doloroso con cui lavorare, ma funziona abbastanza bene una volta superata la curva di apprendimento iniziale.

Vorrei ancora che ci fosse un modo più semplice che fosse altrettanto efficiente?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top