[ Resolvido ] - Dúvidas para ler / alterar elementos específicos em um arquivo Xml

Pessoal estou tendo dificuldades sobre como alterar elementos específicos em um arquivo xml.
O problema é o seguinte: tenho um arquivo com muitos elementos, onde somente me interessa alterar alguns. Antes de mais nada dei uma olhada em http://www.guj.com.br/articles#category_18 aí pensei que o meu caso seria usar o DOM pois ele é melhor para a escrita de documentos para os quais não se tem total domínio da estrutura (esquema).

Vi o exemplo em http://www.guj.com.br/articles/22 mas acho que ele não é bem o meu caso, pois o meu documento xml tem muitos elementos que não me interessam, logo não achei interessante criar uma classe para mapear tudo. Gostaria de colocar o documento em memória, acessar e alterar somente os elementos que preciso. Ou seja, um tipo de filtro.

Estou usando as seguintes classes:
org.w3c.dom.Document;
org.w3c.dom.Element;
org.w3c.dom.Node;
org.w3c.dom.NodeList;

Vocês podem me indicar uma abordagem para esse problema ?

Utilize xpath para achar o Node que você precisa.
Então, você altera ele, rola não?

ex:

DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();

XPath xPath = XPathFactory.newInstance().newXPath();

InputSource is = new InputSource(new ByteArrayInputStream(xml.getBytes()));
Document document = documentBuilder.parse(is);

Element element = (Element) xPath.evaluate("xpath que você quer", document, XPathConstants.NODE);

Acho que assim você vai conseguir alterar com mais facilidade.

Considero o xPath uma abordagem realmente interessante e inteligente. A única coisa é você terá que manter o objeto em memória.
Se você o transformar em um arquivo físico, por exemplo, terá de efetuar a leitura, parser, alteração, parser, escrita e etc…

Fala charlesbraw!

Meu Xml é esse aqui abaixo:

<EMX:Model name="Metas"> <ModelEnvProps> <Locator>Metas.xml</Locator> </ModelEnvProps> <ModelProps> <Name>Metas</Name> </ModelProps> <Entity_Groups> <Entity name="Atividade Area"> <EntityProps> <Name>ATIVIDADE AREA</Name> </EntityProps> <Attribute_Groups> <Attribute name="atar sq atividade area"> <AttributeProps> <Name>ATAR SQ ATIVIDADE AREA</Name> </AttributeProps> </Attribute> <Attribute name="atar nm atividade area"> <AttributeProps> <Name>ATAR NM ATIVIDADE AREA</Name> </AttributeProps> </Attribute> </Attribute_Groups> </Entity> <Entity name="Meta"> <EntityProps> <Name>META</Name> </EntityProps> <Attribute_Groups> <Attribute name="meta sq meta"> <AttributeProps> <Name>META SQ META</Name> </AttributeProps> </Attribute> <Attribute name="meta ds resumida"> <AttributeProps> <Name>META DS RESUMIDA</Name> </AttributeProps> </Attribute> <Attribute name="meta tx detalhada"> <AttributeProps> <Name>META TX DETALHADA</Name> </AttributeProps> </Attribute> <Attribute name="meta in peso"> <AttributeProps> <Name>META IN PESO</Name> </AttributeProps> </Attribute> </Attribute_Groups> </Entity> </Entity_Groups> </EMX:Model>
Preciso alterar todos os elementos que sejam filhos de , ignorando os outros.
Tentei usar o XPath conforme você sugeriu da forma abaixo mas dá NullPointer

	String filepath = "teste.xml";
	DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
	DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
	Document doc = docBuilder.parse(filepath);				  
				
	XPath xPath = XPathFactory.newInstance().newXPath();  				  			 
	Element element = (Element) xPath.evaluate("Name", doc, XPathConstants.NODE);
	System.out.println(element.getTextContent());  // Nullpointer exception nesta linha

O que fiz de errado?

Nesse caso você vai ter que trocar essa linha:

Element element = (Element) xPath.evaluate("Name", doc, XPathConstants.NODE);

por essa:

XPathExpression expr = xPath.compile("/EMX:Model/*"); NodeList nos = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);

ou seja, você vai precisar de uma lista (set) de nós.
Até tentei fazer um exemplo aqui, mas não conseguir acertar o path para seu caso :frowning:
Posso tentar mais depois, mas tenta da uma analisada nisso que falei.

Ah,

E tem a observação do nel, isso tudo está em memória hem. Tem que ainda atualizar o xml depois.

1 curtida

Aqui tém vários exemplos:

http://examples.javacodegeeks.com/core-java/xml/xpath/find-elements-by-absolute-location-with-xpath/

Eu que to saindo com pressa agora, porque vou viajar, senão tentava mais.

1 curtida

Obrigado, pela ajuda, charlesbraw!

Vou continuar tentando com o XPath. Se conseguir algum progresso posto aqui.

Obrigado, charlesbraw! Consegui fazer aqui usando .NODESET conforme você falou. Em seguida fiz as alterações no NodeList e com Transformer gerei um outro xml “parseado”. Importante lembrar do separador no XPath, que deve ser “//” (para uma barra só).

Abraços!

1 curtida