Maenya's Techlog

[20210918] java로 xml 파일 생성하기 - 데이터 파싱작업 본문

개발자의 삶/업무일지

[20210918] java로 xml 파일 생성하기 - 데이터 파싱작업

ming235 2021. 9. 18. 00:44

 

지난 시간에는 Batch 프로그램을 구현하면서 Rest API 를 호출하여 받아온 데이터를 Dto로 변환하는 작업을 했다.

이번에는 Dto에 삽입한 데이터들을 xml 파일을 만들어서 요소와 속성을 채우는 작업을 해볼 것이다.

 

나의 Batch job 중 두번째 step이 될 것이다.

일단은 전반적인 Batch job 로직에 메소드로 만들어서 묶어 버렸는데,

추후에 보기 좋게 로직을 클래스 파일로 따로 빼서 작업할 것이다.

 

 

아래는 xml 파일을 생성하고, 안에 요소와 속성들을 채워넣은 뒤,

임의의 로컬 저장소에 xml 파일을 업로드하는 로직을 간략하게 나타낸 것이다.

 ( * 여기서 Dto 데이터는 전역변수로 사용하고 있었음에 주의)

/**
     * XML 파일 생성하기
     * 일단 여기 메소드로 만들어서 단독 로직파일로 빼내기
     * @return
     */
    @Bean
    public Step step2() {

        ExchangeDto dtoData = exchangeData.get(0);
        try {
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.newDocument();
            doc.setXmlStandalone(true); //standalone="no" 를 없애준다.

            // 요소 생성시작
            Element exInformation = doc.createElement("exInformation");
            doc.appendChild(exInformation);
            Element effectiveDate = doc.createElement("effectiveDate");
            String dateTime = dtoData.getDate() + " " + dtoData.getTime();
            effectiveDate.appendChild(doc.createTextNode(dateTime));
            exInformation.appendChild(effectiveDate);     // 1.고시날짜
            Element currencyCode = doc.createElement("currencyCode");
            currencyCode.appendChild(doc.createTextNode(dtoData.getCurrencyCode()));
            exInformation.appendChild(currencyCode);    // 2.통화코드
            Element exchangeRate = doc.createElement("exchangeRate");
            exchangeRate.appendChild(doc.createTextNode(dtoData.getTtBuyingPrice()));
            exInformation.appendChild(exchangeRate);    // 2.통화코드

            // XML 파일로 쓰기
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); //정렬 스페이스4칸
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //들여쓰기
            transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "yes"); //doc.setXmlStandalone(true); 했을때 붙어서 출력되는부분 개행
            DOMSource source = new DOMSource(doc);
            StreamResult result = new StreamResult(		// xml 파일을 업로드할 저장소 지정
                    new FileOutputStream(new File("D://Asianaiidt/tempUpload/exchangeData.xml")));
			
            transformer.transform(source, result);

            System.out.println("========= xml 파일 생성 완료 =========");

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

        return stepBuilderFactory.get(BATCH_NAME + "Step2")
                .tasklet((stepContribution, chunkContext) -> {
                    log.info((BATCH_NAME + "@@@@@@@  Step2 Started"));
                    return RepeatStatus.FINISHED;
                }).build();
    }

 

이렇게 하고 나면 xml 파일이 아래와 같이 생성된다.

 

부모 노드와 자식노드를 붙이는 append 부분이 약간 헷갈리긴 하는데,

한두번 xml로 출력해보면서 노드에 붙이는 패턴만 잘 파악하면 쉽게 개발할 수 있을 것이다.

 

 

++) 의문점

나는 log를 찍을때 step 1, step2 를 하고 xml 파일생성완료가 나오도록 제작했는데

실제 진행된 로그를 보면 순서가 xml 파일 생성이 먼저 된걸로 나온다.

 

2021-09-18 00:44:40.209  INFO 23536 --- [           main] com.example.batchmvn.BatchJob            : 배치 시작합니다 by 승민========= xml 파일 생성 완료 =========
2021-09-18 00:44:40.322  WARN 23536 --- [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2021-09-18 00:44:41.493  WARN 23536 --- [           main] o.s.b.a.batch.JpaBatchConfigurer         : JPA does not support custom isolation levels, so locks may not be taken when launching Jobs
2021-09-18 00:44:41.499  INFO 23536 --- [           main] o.s.b.c.r.s.JobRepositoryFactoryBean     : No database type set, using meta data indicating: H2
2021-09-18 00:44:41.555  INFO 23536 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : No TaskExecutor has been set, defaulting to synchronous executor.
2021-09-18 00:44:42.141  INFO 23536 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-09-18 00:44:42.181  INFO 23536 --- [           main] c.example.batchmvn.BatchMvnApplication   : Started BatchMvnApplication in 37.828 seconds (JVM running for 45.835)
2021-09-18 00:44:42.186  INFO 23536 --- [           main] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: []
2021-09-18 00:44:42.538  INFO 23536 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=배치 시작합니다 by 승민]] launched with the following parameters: [{}]
2021-09-18 00:44:42.925  INFO 23536 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [배치 시작합니다 by 승민Step1]
2021-09-18 00:44:42.945  INFO 23536 --- [           main] com.example.batchmvn.BatchJob            : 배치 시작합니다 by 승민@@@@@@@ Step1 Started :: testData :::::미국 (KRW/USD)
2021-09-18 00:44:42.957  INFO 23536 --- [           main] o.s.batch.core.step.AbstractStep         : Step: [배치 시작합니다 by 승민Step1] executed in 31ms
2021-09-18 00:44:42.968  INFO 23536 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [배치 시작합니다 by 승민Step2]
2021-09-18 00:44:42.972  INFO 23536 --- [           main] com.example.batchmvn.BatchJob            : 배치 시작합니다 by 승민@@@@@@@  Step2 Started
2021-09-18 00:44:42.977  INFO 23536 --- [           main] o.s.batch.core.step.AbstractStep         : Step: [배치 시작합니다 by 승민Step2] executed in 8ms
2021-09-18 00:44:42.985  INFO 23536 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=배치 시작합니다 by 승민]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 369ms