Синтаксический анализ XML в JAVA - PullRequest
0 голосов
/ 23 сентября 2019

Я новичок в Stackoverflow, поэтому я начинаю понимать, как это работает!:)

Я пишу программу, которая требует, чтобы я проанализировал некоторые XML-файлы, однако я сталкиваюсь с трудностями, так как файл довольно сложный.

Пробовал с помощью DOM, любой совет очень ценится.

<?xml version="1.0" encoding="UTF-8"?>

<REPORT xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <REPORT_HEADER statement_id="4" registered_currency="EUR" run_type="INDIC" publication_timestamp="2019-01-21T22:44:36+00:00" publication_date="2019-01-21" settlement_date="2019-01-20" market_name="B" participant_name="PT" report_type="SS"/>
    <REPORT_SUMMARY>
        <CHARGE_SUMMARY amount="0.0000" date="2019-01-20" name="CPREMIUM"/>
        <CHARGE_SUMMARY amount="-3.8895" date="2019-01-20" name="CUNIMB"/>
    </REPORT_SUMMARY>
    <REPORT_DETAIL>
        <RESOURCE name="GU">
            <CHARGE name="CAB">
                <VALUE amount="3.0000" datetime="2019-01-20T00:30:00+00:00"/>
                <VALUE amount="0.0000" datetime="2019-01-20T01:30:00+00:00"/>
            </CHARGE>
            <CHARGE name="CPO">
                <VALUE amount="0.0000" datetime="2019-01-20T00:30:00+00:00"/>
                <VALUE amount="0.0000" datetime="2019-01-20T01:30:00+00:00"/>
            </CHARGE>
        </RESOURCE>
        <RESOURCE name="PU">
            <CHARGE name="COD">
                <VALUE amount="0.0000" datetime="2019-01-20T00:30:00+00:00"/>
                <VALUE amount="0.0000" datetime="2019-01-20T01:30:00+00:00"/>
            </CHARGE>
            <CHARGE name="MOD">
                <VALUE amount="1.0000" datetime="2019-01-20T00:30:00+00:00"/>
                <VALUE amount="2.0000" datetime="2019-01-20T01:30:00+00:00"/>
            </CHARGE>
        </RESOURCE>
    </REPORT_DETAIL>
</REPORT>

Требуемый вывод, к которому я стремлюсь.

CHARGE_SUMMARY amount="0.0000" date="2019-01-20" name="CPREMIUM"
CHARGE_SUMMARY amount="-3.8895" date="2019-01-20" name="CUNIMB"

RESOURCE name="GU" CHARGE name="CAB" amount="3.0000" datetime="2019-01-20T00:30:00+00:00"
RESOURCE name="GU" CHARGE name="CAB" amount="0.0000" datetime="2019-01-20T01:30:00+00:00"
RESOURCE name="GU" CHARGE name="CPO" amount="0.0000" datetime="2019-01-20T00:30:00+00:00"
RESOURCE name="GU" CHARGE name="CPO" amount="0.0000" datetime="2019-01-20T01:30:00+00:00"

RESOURCE name="PU" CHARGE name="COD  VALUE amount="0.0000" datetime="2019-01-20T00:30:00+00:00"
RESOURCE name="PU" CHARGE name="COD  VALUE amount="0.0000" datetime="2019-01-20T01:30:00+00:00"
RESOURCE name="PU" CHARGE name="MOD" VALUE amount="1.0000" datetime="2019-01-20T00:30:00+00:00"
RESOURCE name="PU" CHARGE name="MOD" VALUE amount="2.0000" datetime="2019-01-20T00:30:00+00:00"

Я могу выполнить синтаксический анализ CHARGE_SUMMARY с помощью DOM, см. Ниже

 package Project;

 import java.io.File;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.DocumentBuilder;
 import org.w3c.dom.Document;
 import org.w3c.dom.NodeList;
 import org.w3c.dom.Node;
 import org.w3c.dom.Element;

 import java.util.*; // Required for Hashmap


 public class Parse_File_SS{

 public HashMap<String,ArrayList<String>> parsing_SS(String path , String report_type){

    String path_location = path;
 System.out.println("Parsing SS: " + "String: "+ path_location);

 String report = report_type;
 System.out.println("Report type: "+ report);

 HashMap<String,ArrayList<String>> hm=new HashMap<String,ArrayList<String>>();  

 try {
 File inputFile = new File(path_location);
 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
 DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
 Document doc = dBuilder.parse(inputFile);
 doc.getDocumentElement().normalize();
 //[GETTING ROOT ELEMENT]
 System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
  NodeList nList1 = doc.getElementsByTagName("CHARGE_SUMMARY");
   //Iterating through CHARGE_SUMMARY List, within REPORT_SUMMARY******************************************************************
      for (int temp = 0; temp < nList1.getLength(); temp++) {
                        Node nNode = nList1.item(temp);
                        System.out.println("\nCurrent Element :" + nNode.getNodeName());

                        //Get Values Associated with Charge Summary

                        //1. amount
                        if (nNode.getNodeType() == Node.ELEMENT_NODE) {
                            Element eElement = (Element) nNode;
                            System.out.println("amount : " 
                               + eElement.getAttribute("amount"));
                        }
                        //2. date
                        if (nNode.getNodeType() == Node.ELEMENT_NODE) {
                            Element eElement = (Element) nNode;
                            System.out.println("date : " 
                               + eElement.getAttribute("date"));
                        }
                        //3. name
                        if (nNode.getNodeType() == Node.ELEMENT_NODE) {
                            Element eElement = (Element) nNode;
                            System.out.println("name : " 
                               + eElement.getAttribute("name"));
                        }
      } //     

Однакониже, где я сталкиваюсь с проблемой, используя NodeList nList3 = doc.getElementsByTagName ("CHARGE");Я перебираю все сборы, а не конкретные требуемые сборы

  //**********[GETTING TAGNAME: REPORT_DETAIL]******************************************************************           
   NodeList nList3 = doc.getElementsByTagName("CHARGE");
   System.out.println("-----------CHARGE-----------------");         


        //We need to iterate through the CHARGE within RESOURCE within REPORT_DETAIL******************************************************
        for (int temp3 = 0; temp3 < nList3.getLength(); temp3++) {  

                 Node nNode3 = nList3.item(temp3);
                 System.out.println("\nCurrent Element :" + nNode3.getNodeName());
            if (nNode3.getNodeType() == Node.ELEMENT_NODE) {
                    Element eElement3 = (Element) nNode3;
                    System.out.println("name : "  + eElement3.getAttribute("name"));


              //**** If  [1]  CHARGE_SUMMARY  name = CAB   ********************************************************************************                      
                          // now if name = CAB iterate through the values

                            if(eElement3.getAttribute("name").contains("CAB")) { 
                                System.out.println("CAB is Present");

                          //**********[GETTING TAGNAME: VALUE]**************************************************************    
                               NodeList nList_CAB = doc.getElementsByTagName("CAB");   //Get the list of values                                
                               System.out.println("The Length of the list is CAB: "+nList_CAB.getLength());

Длина списка равна нулю, что является проблемой,

                           //Now iterate through them
                                         for (int temp_CAB = 0; temp_CAB < nList_CAB.getLength(); temp_CAB++) {
                                                Node nNode_CAB = nList_CAB.item(temp_CAB);
                                                System.out.println("\nCurrent Element of values:" + nNode_CAB.getNodeName()); 

                                          //1. date time
                                            if (nNode_CAB.getNodeType() == Node.ELEMENT_NODE) {
                                                    Element eElement_CAB = (Element) nNode_CAB;
                                                    System.out.println("datetime : "  + eElement_CAB.getAttribute("datetime"));
                                            }
                                          //2. amount
                                            if (nNode_CAB.getNodeType() == Node.ELEMENT_NODE) {
                                                    Element eElement_CAB = (Element) nNode_CAB;
                                                    System.out.println("amount : " + eElement_CAB.getAttribute("amount"));

                                             }
                                           }   
                                       }               
                }    
  }

    } catch (Exception e) {
       e.printStackTrace();

    }       
       return hm;
    }

Ответы [ 2 ]

0 голосов
/ 23 сентября 2019

Java / DOM - ужасно низкоуровневый инструмент для этой работы.XSLT имеет некоторую кривую обучения, но в итоге получается гораздо меньше кода.Вот решение в XSLT 3.0 (самым сложным было получить пустые строки в нужном месте):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0" expand-text="yes">
    <xsl:strip-space elements="*"/>
    <xsl:output method="text"/>
    <xsl:template match="REPORT_SUMMARY/CHARGE_SUMMARY">
        <xsl:text>CHARGE SUMMARY amount={@amount} date={@date} name={@name}&#xa;</xsl:text>      
    </xsl:template>
    <xsl:template match="RESOURCE">
        <xsl:text>&#xa;</xsl:text>
        <xsl:apply-templates/>
    </xsl:template>
    <xsl:template match="RESOURCE/CHARGE/VALUE">
        <xsl:text>RESOURCE name={../../@name} CHARGE name={../@name} VALUE amount={@amount} datetime={@datetime}&#xa;</xsl:text>
    </xsl:template>
</xsl:stylesheet>

Вы можете запустить это, установив Saxon-HE из SourceForge и запустив его прямо из командной строки.:

java -jar saxon9he.jar -s:input.xml -xsl:stylesheet.xsl

или вы можете использовать API для его запуска из вашего Java-приложения.

Как это работает: процессор запускается в корневом узле в поисках соответствующего правила шаблона.Если его нет, он понижается до уровня и т. Д. Рекурсивно.Здесь есть три правила шаблона: одно срабатывает, когда вы нажимаете CHARGE_SUMMARY, другое - когда вы нажимаете VALUE, и они просто выводят контент довольно очевидным способом.Шаблон match = "RESOURCE" предназначен только для вывода пустых строк между смежными ресурсами;он выводит новую строку (&#xa; в XML) и затем вызывает xsl: apply-templates, что означает «теперь обрабатывать следующий уровень вниз, используя соответствующие правила шаблона».

0 голосов
/ 23 сентября 2019

Я бы использовал XPath для этого, так как я думаю, что это делает намерение более ясным:

public static void main(String... args)
        throws Exception
{
    // BEGIN: DOM Boilerplate
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document doc = builder.parse(new File("input.xml"));
    XPathFactory xPathfactory = XPathFactory.newInstance();
    XPath xpath = xPathfactory.newXPath();
    // END: DOM Boilerplate

    // Find and iterate over CHARGE_SUMMARY nodes
    XPathExpression chargeQuery = xpath.compile("/REPORT/REPORT_SUMMARY/CHARGE_SUMMARY");
    NodeList chargeSummaries = (NodeList) chargeQuery.evaluate(doc, XPathConstants.NODESET);
    for (int i = 0; i < chargeSummaries.getLength(); i++) {
        Element chargeSummary = (Element) chargeSummaries.item(i);

        System.out.printf("CHARGE_SUMMARY amount=\"%s\" date=\"%s\" name=\"%s\"%n",
                chargeSummary.getAttribute("amount"),
                chargeSummary.getAttribute("date"),
                chargeSummary.getAttribute("name"));
    }

    // Find and iterate over VALUE nodes
    XPathExpression valueQuery = xpath.compile("/REPORT/REPORT_DETAIL/RESOURCE/CHARGE/VALUE");
    NodeList values = (NodeList) valueQuery.evaluate(doc, XPathConstants.NODESET);
    String lastResourceName = null;
    for (int i = 0; i < values.getLength(); i++) {
        Element value = (Element) values.item(i);

        String resourceName = ((Element) value.getParentNode().getParentNode()).getAttribute("name");

        if (!resourceName.equals(lastResourceName)) {
            lastResourceName = resourceName;
            System.out.println();
        }

        System.out.printf("RESOURCE name=\"%s\" CHARGE name=\"%s\" VALUE amount=\"%s\" datetime=\"%s\"%n",
                resourceName,
                ((Element) value.getParentNode()).getAttribute("name"),
                value.getAttribute("amount"),
                value.getAttribute("datetime"));
    }
}

И это вывод:

CHARGE_SUMMARY amount="0.0000" date="2019-01-20" name="CPREMIUM"
CHARGE_SUMMARY amount="-3.8895" date="2019-01-20" name="CUNIMB"

RESOURCE name="GU" CHARGE name="CAB" VALUE amount="3.0000" datetime="2019-01-20T00:30:00+00:00"
RESOURCE name="GU" CHARGE name="CAB" VALUE amount="0.0000" datetime="2019-01-20T01:30:00+00:00"
RESOURCE name="GU" CHARGE name="CPO" VALUE amount="0.0000" datetime="2019-01-20T00:30:00+00:00"
RESOURCE name="GU" CHARGE name="CPO" VALUE amount="0.0000" datetime="2019-01-20T01:30:00+00:00"

RESOURCE name="PU" CHARGE name="COD" VALUE amount="0.0000" datetime="2019-01-20T00:30:00+00:00"
RESOURCE name="PU" CHARGE name="COD" VALUE amount="0.0000" datetime="2019-01-20T01:30:00+00:00"
RESOURCE name="PU" CHARGE name="MOD" VALUE amount="1.0000" datetime="2019-01-20T00:30:00+00:00"
RESOURCE name="PU" CHARGE name="MOD" VALUE amount="2.0000" datetime="2019-01-20T01:30:00+00:00"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...