XML Parsing (SAX, DOM, XPath)

Задача от Алексея. По работе часто приходится сталкиваться с задачей по обработке XML сообщений. Заменить теги, значение тегов, размаршалить и тд. Формат XML очень популярная тема для обмена сообщениями, рассмотрим несколько примеров возможной работы с этим форматом.

Задание:
Имеем csv/txt файл с набором данных. Распарсить файл, собрать XML сообщение. Сохранить в файл.
Из полученной XML достать объекты (распарсить XML) несколькими способами. Заменить значение тегов в XML у исходной и сохранить новую XML.
Заменить блок значений в XML (добавить/удалить). Изменить наименование тега в XML.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<ActorCast xmlns="https://www.gotoqa.ru/actors">
    <Cast id="1">
        <Character>
            <FirstName>Daenerys</FirstName>
            <LastName>Targaryen</LastName>
        </Character>
        <Actor>
            <FirstName>Emilia</FirstName>
            <LastName>Clarke</LastName>
            <BirthDay>23 October 1986</BirthDay>
        </Actor>
    </Cast>
</ActorCast>

Также в XML
– id = 2, сменить на id = 20;
– У актера id = 2, сменить блок Character;
– Добавить блок Cast id=”21″ с произвольными данными;
– Удалить блок Cast id=”10″;

Использовал:

SAX DOM XPath

Начать нужно с теории по XML: w3schools
Кода получилось много, поэтому выложу отрывки и как всегда полный проект доступен на GitHub

SAX Parser

SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
 
DefaultHandler handler = new DefaultHandler() {
boolean bfname = false;
boolean blname = false;
boolean birthDay = false;
public void startElement(String uri, String localName, String qName,
						 Attributes attributes) {
	System.out.println("Start Element: " + qName);
 
	if (qName.equalsIgnoreCase("FIRSTNAME")) {
		bfname = true;
	}
	if (qName.equalsIgnoreCase("LASTNAME")) {
		blname = true;
	}
	if (qName.equalsIgnoreCase("BirthDay")) {
		birthDay = true;
	}

DOM Parser

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder loader = factory.newDocumentBuilder();
Document document = loader.parse("D:\\JAVA\\Java_SRC\\XMLParsingProject\\src\\main\\resources\\act.xml");
DocumentTraversal trav = (DocumentTraversal) document;
MyFilter filter = new MyFilter();
NodeIterator it = trav.createNodeIterator(document.getDocumentElement(),
		NodeFilter.SHOW_ELEMENT, filter, true);
for (Node node = it.nextNode(); node != null;
	 node = it.nextNode()) {
 
	String name = node.getNodeName();
	String text = node.getTextContent().trim().replaceAll("\\s+", " ");
	System.out.printf("%s: %s%n", name, text);
	System.out.println("==========================================");
}
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(xmlFilePath);
 
Node employee = document.getElementsByTagName("Cast").item(1);
 
NamedNodeMap attribute = employee.getAttributes();
Node nodeAttr = attribute.getNamedItem("id");
nodeAttr.setTextContent("20");
 
Node nodeAttr2 = document.getElementsByTagName("FirstName").item(0);
nodeAttr2.setTextContent("FnameUPDATE");
 
Node nodeAttr3 = document.getElementsByTagName("LastName").item(0);
nodeAttr3.setTextContent("LnameUPDATE");
 
TransformerFactory transformerFactory = TransformerFactory.newInstance();
 
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
String filePath = "D:\\JAVA\\Java_SRC\\XMLParsingProject\\src\\main\\resources\\act.xml";
File xmlFile = new File(filePath);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder;
try {
	dBuilder = dbFactory.newDocumentBuilder();
	Document doc = dBuilder.parse(xmlFile);
	doc.getDocumentElement().normalize();
	System.out.println("Root element: " + doc.getDocumentElement().getNodeName());
	NodeList nodeList = doc.getElementsByTagName("Actor");
	List<ActorsModel> actorsList = new ArrayList<>();
	for (int i = 0; i < nodeList.getLength(); i++) {
		actorsList.add(getActors(nodeList.item(i)));
	}
	for (ActorsModel act : actorsList) {
		System.out.println(act.getFirstName().toString());
	}

XPATH Parser

XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xpath = xpathFactory.newXPath();
 
XPathExpression expr =
                            xpath.compile("//*[local-name()='BIC'][" + i + "]" + "//*[local-name()='BIC'][\" +i+ \"]");
                    String nodes = (String) expr.evaluate(doc, XPathConstants.STRING);

Ссылка на GitHub:
Github XML Parsing (SAX, DOM, XPath)

Releated Post