Pergunta

eu tenho um XmlDocument em java, criado com o Weblogic XmlDocument analisador.

Quero substituir o conteúdo de uma tag neste XMLDocument com meus próprios dados ou insira a tag se ela não estiver lá.

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

Por exemplo, quero inserir algum URL na tag de localização:

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

mas caso contrário, deixe o XML como está.

Atualmente eu uso um 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();
    }

Eu tentei encontrar um "rápido" xquery maneira de fazer isso desde o XmlDocument tem um execQuery método, mas não achei muito fácil.

Alguém tem uma maneira melhor do que esta?Parece um pouco elaborado.

Foi útil?

Solução

Que tal uma abordagem baseada em XPath?Gosto dessa abordagem porque a lógica é muito fácil de entender.O código é praticamente autodocumentado.

Se o seu documento xml estiver disponível como um objeto org.w3c.dom.Document (como a maioria dos analisadores retorna), você poderá fazer algo como o seguinte:

// 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 );
  }
}

E aqui está o método auxiliar findNodes que faz a pesquisa 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 );
}

Outras dicas

Que tal uma abordagem orientada a objetos?Você pode desserializar o XML para um objeto, definir o valor do local no objeto e serializar novamente para XML.

XStream torna isso muito fácil.

Por exemplo, você definiria o objeto principal, que no seu caso é CustomData (estou usando campos públicos para manter o exemplo simples):

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

Então você inicializa o XStream:

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

Agora você pode construir um objeto a partir de XML, definir o campo de localização no objeto e gerar novamente o XML:

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

Como isso soa?

Se você não conhece o esquema, a solução XStream provavelmente não é a melhor opção.Pelo menos o XStream está no seu radar agora, pode ser útil no futuro!

Você deve ser capaz de fazer isso com query

tentar

 fn:replace(string,pattern,replace)

Eu sou novo no xquery e descobri que é uma linguagem de consulta difícil de trabalhar, mas funciona bem quando você supera a curva de aprendizado inicial.

Eu ainda gostaria que houvesse uma maneira mais fácil e tão eficiente?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top