• Home
  • About
    • Young's Github Pages photo

      一日不作一日不食

    • About
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

Java EE 정리 21

27 Mar 2019

Reading time ~8 minutes

Java EE 정리 21 - XML 생성, DTD


JDOM Parser를 이용한 Attribute Parsing

  • 노드에 속성(Attribute)를 Parsing할 수 있다.
<?xml ... >
<부모노드>
    <자식노드 속성명="값" />
    ...
</부모노드>
// 노드 얻기
Element el = rootNode.getChilde("자식노드명");

// 속성 얻기
Attribute attr = el.getAttribute("속성명");

// 속성의 값 얻기
String attrVal = attr.getValue();
  • 속성 Parsing 예
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<people>
      <person>
            <name lastName="김">정윤</name>
            <address city="강남구" zipcode="12345">신사동</address>
      </person>
      <person>
            <name lastName="김">희철</name>
            <address city="관악구" zipcode="36454">신사동</address>
      </person>
      <person>
            <name lastName="노">진경</name>
            <address city="강서구" zipcode="76543">강화동</address>
      </person>
      <person>
            <name lastName="김">민정</name>
            <address city="관악구" zipcode="66542">청림동</address>
      </person>
      <person>
            <name lastName="정">택성</name>
            <address city="구로구" zipcode="76543">개봉동</address>
      </person>
</people>
public class AttrVO {
      
      private String firstName, lastName, city, zipcode, address;
      // 기본,인자있는 생성자, getter, setter .. 
      ...
public class AttrParsing {
      
      public List<AttrVO> personDataParsing(String lastName) throws  MalformedURLException, JDOMException, IOException {
            List<AttrVO> list = new ArrayList<AttrVO>();
            
            // 1. Builder(Parser) 생성
            SAXBuilder sb = new SAXBuilder();
            
            // 2. XML 읽기
            Document doc = sb.build(new  URL("http://localhost:8080/jsp_prj/xml0327/attr.xml"));
            
            // 3. 최상위 부모노드 얻기
            Element peopleNode = doc.getRootElement();
            
            // 4. 처음 자식노드들 얻기
            Iterator<Element> personNodes =  peopleNode.getChildren().iterator();
            
            Element personNode = null;
            Element personSubNode = null;
            Attribute lastNameAttr = null;
            Attribute cityAttr = null;
            Attribute zipcodeAttr = null;
            String lastNameAttrVal = "";
            AttrVO avo = null;
            
            // 5. people 자식노드만큼 반복
            while(personNodes.hasNext()) {
                  
                  // person 노드 얻기
                  personNode = personNodes.next();
                  
                  // person의 자식 노드들 얻기
                  Iterator<Element> personSubNodes =  personNode.getChildren().iterator();
                  
                  while(personSubNodes.hasNext()) {
                        personSubNode = personSubNodes.next(); // name,  address
                        
                        // 1. name 노드면
                        if ("name".equals(personSubNode.getName())) {
                              // lastName 속성값을 구하고
                              lastNameAttr =  personSubNode.getAttribute("lastName");
                              lastNameAttrVal = lastNameAttr.getValue();
                              // 성이 같으면 VO 생성
                              if (lastName.equals(lastNameAttrVal)) {
                                    avo = new AttrVO();
                                    // 이름 set
                                    avo.setLastName(lastNameAttrVal);
                                    avo.setFirstName(personSubNode.getText());
                              }
                        }
                        
                        // 2. 성이 같다면
                        if (lastName.equals(lastNameAttrVal)) {
                              // 주소 노드의 값 set
                              if  ("address".equals(personSubNode.getName())) {
                                    
                                    cityAttr =  personSubNode.getAttribute("city");
                                    zipcodeAttr =  personSubNode.getAttribute("zipcode");
                                    
                                    // 주소를 set
                                    avo.setCity(cityAttr.getValue());
                                    avo.setZipcode(zipcodeAttr.getValue());
                                    avo.setAddress(personSubNode.getText());

                                    list.add(avo);
                              }
                        }
                  }
            }
            
            return list;
      }
}
<!-- attr_parsing.jsp -->
...
<script type="text/javascript">
      $(function() {
            
            $("#btn").click(function() {
                  $("[name='frm']").submit();
            });
            
      }); // ready
</script>
...
<div>
<form name="frm" action="attr_parsing.jsp" method="get">
      <select id="lastName" name="lastName">
            <option value="김">김씨</option>
            <option value="이">이씨</option>
            <option value="박">박씨</option>
            <option value="정">정씨</option>
            <option value="노">노씨</option>
            <option value="최">최씨</option>
      </select>
      <input type="button" value="조회" id="btn" class="btn"/>
</form>
</div>
<c:if test="${ not empty param.lastName }">
<div>
      <div>선택하신 "${ param.lastName }"으로 조회한 결과입니다.</div>
      <div>
      <%
            String lastName = request.getParameter("lastName");
            
            AttrParsing ap = new AttrParsing();
            
            List<AttrVO> list = ap.personDataParsing(lastName);
            pageContext.setAttribute("personList", list);
      %>
      <table border="1">
            <tr>
                  <th width="100">이름</th>
                  <th width="400">주소</th>
            </tr>
            <c:if test="${ empty personList }">
            <tr>
                  <td colspan="2" align="center">검색결과가 존재하지 않습니다.</td>
            </tr>
            </c:if>
            <c:forEach var="data" items="${ personList }">
            <tr>
                  <td><c:out value="${ data.lastName }"/><c:out  value="${ data.firstName }"/></td>
                  <td>(${ data.zipcode }) ${ data.city } ${ data.address }</td>
            </tr>
            </c:forEach>
      </table>
      </div>
</div>
</c:if>
...

01

XML 생성 - Java로 만들기

  • XML은 Java 또는 JDOM Parser로 만들 수 있다.
  • XML을 만드는 작업을 Thread로 수행하면 지속적으로 XML을 업데이트 할 수 있음
  • Java로 XML 만들기
    • DB로부터 데이터 얻기
    • 얻은 데이터로 XML형태의 String 생성
    • 출력스트림으로 XML 출력
public class CreateXML {
      
      public List<String> data() {
            List<String> list = new ArrayList<String>();
            
            list.add("월래 먹는 날");
            list.add("화끈하게 먹는 날");
            list.add("수도없이 먹는 날");
            list.add("목이 터지게 먹는 날");
            list.add("금새먹고 또 먹는 날");
            list.add("토하면서 먹는 날");
            list.add("일일이 찾아다니며 먹는 날");
            
            return list;
      }     
      
      public String createXML(List<String> weekMsg) {
            StringBuilder xml = new StringBuilder();
            
            xml.append("<?xml version='1.0' encoding='UTF-8'?>\n");
            xml.append("<week>\n");
            
            for(int i=0; i < weekMsg.size(); i++) {
                  xml.append("\t<msg>").append(weekMsg.get(i)).append("</msg>\n");
            }
            
            xml.append("</week>");
            
            return xml.toString();
      }
      
      public void createXMLFile(String xml) throws IOException {
            BufferedWriter bw = null;
            
            try {
                  bw = new BufferedWriter(new OutputStreamWriter(
                        new  FileOutputStream("C:/.../msg.xml"),"UTF-8"));
                  
                  bw.write(xml);
                  bw.flush();
            } finally {
                  if (bw != null) { bw.close(); }
            }
      }

      public static void main(String[] args) {
            CreateXML c = new CreateXML();
            
            try {
                  c.createXMLFile(c.createXML(c.data()));
            } catch (IOException e) {
                  e.printStackTrace();
            }
      }
}

02

XML 생성 - Parser로 만들기

  • XML 문서 객체 생성
    • 선언부가 생성됨
Document doc = new Document(); // <? xml ... ?>
  • 최상위 부모 노드를 생성
    • 한개만 생성
Element rootNode = new Element("부모노드");
  • 자식노드 생성
    • 여러개 생성가능
Element subNode1 = new Element("자식노드1"); // <자식노드1/>
Element subNode2 = new Element("자식노드2");
Element subNode3 = new Element("자식노드3");
  • 자식노드에 들어갈 값 설정
subNode1.setText("값1"); // <자식노드1>값1</자식노드1>
subNode2.setText("값2");
subNode3.setText("값3");
  • 속성을 가지는 경우
// 속성객체 생성
Attribute attr = new Attribute("속성명1", "속성값1");

// 속성객체를 노드객체에 추가
subNode1.setAttribute(attr); // <자식노드1 속성명1="속성값1">값1</자식노드1>
  • 자식노드를 부모노드에 추가(반복)
rootNode.addContent(subNode1);
rootNode.addContent(subNode2);
rootNode.addContent(subNode3);

/*
<부모노드>
    <자식노드1 속성명1="속성값1">값1<자식노드1>
    <자식노드2>값2</자식노드2>
    <자식노드3>값3</자식노드3>
</부모노드>
*/
  • 자식노드를 가진 부모노드를 문서객체에 추가
doc.addContent(rootNode);

/*
<? xml ... ?>
<부모노드>
    <자식노드1 속성명1="속성값1">값1<자식노드1>
    <자식노드2>값2</자식노드2>
    <자식노드3>값3</자식노드3>
</부모노드>
*/
  • 출력 객체 생성 후 출력
    • 콘솔, 파일, 네트워크 등 다양하게 출력가능
XMLOutputter xout = new XMLOutputter();

xout.output(doc, 출력스트림);
  • JDOM Parser로 XML 생성 예
public class CreateJdomXml {
    
    public List<String> data() {
        List<String> list = new ArrayList<String>();
        
        list.add("월래 먹는 날");
        list.add("화끈하게 먹는 날");
        list.add("수도없이 먹는 날");
        list.add("목이 터지게 먹는 날");
        list.add("금새먹고 또 먹는 날");
        list.add("토하면서 먹는 날");
        list.add("일일이 찾아다니며 먹는 날");
        
        return list;
    }    
    
    public Document createXML(List<String> weekMsg) {
        // 1. XML 문서객체 생성
        Document doc = new Document();
        
        // 2. 최상위 부모 노드를 생성
        Element rootNode = new Element("week");
        
        Element msgNode = null;
        for(String data : weekMsg) {
            // 3. 자식노드를 생성
            msgNode = new Element("msg");

            // 4. 자식 노드에 들어갈 값 설정
            msgNode.setText(data);
            
            // 5. 값을 가진 자식 노드를 부모 노드에 할당
            rootNode.addContent(msgNode);
        }
        
        // 6. 자식노드를 가진 부모노드를 XML 문서객체에 추가
        doc.addContent(rootNode);
        
        return doc;
    }
    
    public void createXMLFile(Document doc) throws IOException {
        // 7. 출력 객체 생성
        XMLOutputter xout = new XMLOutputter();
        
        // 8. XML 문서객체와 출력스트림을 사용하여 출력
        xout.output(doc, System.out);
    }


    public static void main(String[] args) {
        CreateJdomXml c = new CreateJdomXml();
        
        try {
            c.createXMLFile(c.createXML(c.data()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

03

  • 출력객체로 출력할 때 format을 설정가능
    • compact, raw format - 한줄로 출력
    • pretty format - 줄바꿔 출력
// 7. 출력 객체 생성
// XMLOutputter xout = new  XMLOutputter(Format.getCompactFormat());
// XMLOutputter xout = new XMLOutputter(Format.getRawFormat());
XMLOutputter xout = new  XMLOutputter(Format.getPrettyFormat());

04

public void createXMLFile(Document doc) throws IOException {
      // 7. 출력 객체 생성
      XMLOutputter xout = new XMLOutputter(Format.getPrettyFormat());
      
      // 8. XML 문서객체와 출력스트림을 사용하여 출력
      xout.output(doc, new FileOutputStream("C:/.../jdom.xml"));
}

05

  • 속성 있을 때, XML 생성 예
public class DataVO {
      private String carModel, company, owner, carType; // carType을 속성으로 줄 것
      private int cc;
      ... // 기본생성자, 인자있는 생성자, setter, getter
public class CreateJdomAttrXml {
    
    public List<DataVO> data() {
      List<DataVO> list = new ArrayList<DataVO>();
      
      list.add(new DataVO("아반테", "현대", "김정윤", "승용", 1600));
      list.add(new DataVO("솔리드프로", "넥슨", "김희철", "스포츠카", 3000));
      list.add(new DataVO("연습용카트", "넥슨", "공선의", "스포츠카", 800));
      list.add(new DataVO("소렌토", "기아", "이재찬", "SUV", 4800));
      list.add(new DataVO("MAN트럭", "MAN", "노진경", "트럭", 10000));
      
      return list;
    }    
    
    public Document createXML(List<DataVO> carList) {
      // 1. XML 문서객체 생성
      Document doc = new Document();
      
      // 2. 최상위 부모노드를 생성
      Element rootNode = new Element("cars");
      
      // 자식노드 선언
      Element carNode = null;
      Element carModelNode = null;
      Element companyNode = null;
      Element ownerNode = null;
      Element ccNode = null;
      
      // 속성 선언
      Attribute carTypeAttr = null;
      
      for(DataVO data: carList) {
      // 3. 자식노드를 생성, 4. 값 설정
      carNode = new Element("car");

      carModelNode = new Element("model");
      carModelNode.setText(data.getCarModel());
      
      companyNode = new Element("company");
      companyNode.setText(data.getCompany());
      
      ownerNode = new Element("owner");
      ownerNode.setText(data.getOwner());
      
      ccNode = new Element("cc");
      ccNode.setText(String.valueOf(data.getCc()));
      
      // 속성 선언
      carTypeAttr = new Attribute("type", data.getCarType());
      // 속성 설정
      carNode.setAttribute(carTypeAttr);
      
      // 5. 값을 가진 자식 노드를 부모 노드에 할당
      // car 노드에 자식노드 추가
      carNode.addContent(carModelNode);
      carNode.addContent(companyNode);
      carNode.addContent(ownerNode);
      carNode.addContent(ccNode);
      
      // 자식 노드를 가진 car노드를 최상위 부모노드에 배치
      rootNode.addContent(carNode);
      }
      
      // 6. 자식노드를 가진 부모노드를 XML 문서객체에 추가
      doc.addContent(rootNode);
      
      return doc;
    }
    
    public void createXMLFile(Document doc) throws IOException {
      // 7. 출력 객체 생성, compact, raw format은 한줄로 출력
      XMLOutputter xout = new XMLOutputter(Format.getPrettyFormat());
      
      // 8. XML 문서객체와 출력스트림을 사용하여 출력
      // xout.output(doc, System.out);
      xout.output(doc, new FileOutputStream("C:/.../jdom_car.xml"));
    }
}

06

DTD(Document Type Definition)

  • DTD도 하나의 XML, 확장자만 DTD
  • XML 작성 규칙을 설정하는 일을 함
    • DTD 없는 XML은 Well-Formed Document(적격문서)
    • DTD 있는 XML은 Valid Document(유효문서)
      • Valid Document는 작성규칙과 DTD에 정의된 규칙을 모두 지켜서 만들어야 한다.
      • DTD를 사용한 XML이 작성규칙을 지키지 않으면 Error가 발생
  • 복잡한 제어를 할 때에는 XML Schema 작성
  • 작성 규칙 - 태그의 등장순서, 등장 횟수, 속성 정보
    • 간단한 구조를 가진다
    • 기호를 가지고 설정
  • 사용 기호

07

08

  • 작성법
    • 노드명이 중복되면 가장 마지막 선언된 것만 들어간다.
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT 노드명 (자식노드명,...)> <!-- 노드와 자식노드 정의, ()안, 뒤에 기호사용 -->
<!ELEMENT 자식노드명 (#PCDATA)>
...
<!ATTLIST 노드명 속성명 CDATA #REQUIRE> <!-- 속성 정의, #~는 사용옵션 -->
<!ATTLIST 노드명 속성명 CDATA #FIXED "고정값">
<!ATTLIST 노드명 속성명 CDATA #IMPLIED>
  • 필요한 XML에서 선언부를 정의하여 DTD를 사용한 XML 작성
<?xml version="1.0" encoding="UTF-8" standalone="false"?>
<!DOCTYPE 적용할노드명 SYSTEM "test.dtd">
<노드명>
    <자식노드명>
...
  • DTD 사용 예 1 - hello.dtd
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT root (msg*)>
<!ELEMENT msg (#PCDATA)>
  • DTD 사용 예 1 - hello.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE root SYSTEM "hello.dtd">
<root>
      <msg>안녕 XML!</msg>
      <msg>오늘은 화요일이야</msg>
</root>

09

  • DTD 사용 예 2 - depts.dtd
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT depts (dept+)>
<!ELEMENT dept (deptno?, dname+, loc*)>
<!ELEMENT deptno (#PCDATA)>
<!ELEMENT dname (#PCDATA)>
<!ELEMENT loc (#PCDATA)>
  • DTD 사용 예 2 - depts.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE depts SYSTEM "depts.dtd">
<!-- 부서 정보를 저장하는 XML -->
<depts>
      <dept>
            <deptno>10</deptno>
            <dname>SI 개발부</dname>
            <loc>서울</loc>
      </dept>
      <dept>
            <deptno>20</deptno>
            <dname>SM 유지보수</dname>
            <loc>경기</loc>
      </dept>
      <dept>
            <deptno>30</deptno>
            <dname>SE</dname>
            <loc>서울</loc>
      </dept>
      <dept>
            <deptno>40</deptno>
            <dname>QA</dname>
            <loc>부산</loc>
      </dept>
</depts>

10

  • DTD 사용 예 3 - computer.dtd
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT computers (computer)*>
<!ELEMENT computer (cpu+, motherBoard?, ram+, powerSupply+, (hdd?|sdd?),  odd?, vga?)>
<!ELEMENT cpu (#PCDATA)>
<!ELEMENT motherBoard (#PCDATA)>
<!ELEMENT ram (#PCDATA)>
<!ELEMENT powerSupply (#PCDATA)>
<!ELEMENT hdd (#PCDATA)>
<!ELEMENT sdd (#PCDATA)>
<!ELEMENT odd (#PCDATA)>
<!ELEMENT vga (#PCDATA)>

<!ATTLIST cpu brand CDATA #REQUIRED>
<!ATTLIST motherBoard brand CDATA #REQUIRED>
<!ATTLIST hdd brand CDATA #REQUIRED>
<!ATTLIST vga brand CDATA #FIXED "NVIDIA">
  • DTD 사용 예 3 - computer.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE computers SYSTEM "computer.dtd">
<computers>
      <computer>
            <cpu brand="intel">i5 3.3GHz</cpu>
            <motherBoard brand="GIGABYTE">GM001</motherBoard>
            <ram>16GB</ram>
            <powerSupply>7team</powerSupply>
            <hdd brand="WD">1TB</hdd>
            <odd>LG</odd>
            <vga brand="NVIDIA">GTX2080Ti</vga>
      </computer>
</computers>

11



Java EEXML