-
Notifications
You must be signed in to change notification settings - Fork 36
28장 working with xml
outsideris edited this page Sep 5, 2012
·
1 revision
##28.1 Semi-structured data
- 스칼라는 XML처리를 지원한다.
##28.2 XML overview
- 그냥 XML 설명임
##28.3 XML literals
- XML을 리터럴로 사용할 수 있다.
scala> <a>
This is some XML.
Here is a tag: <atag/>
</a>
res0: scala.xml.Elem = ...
-
XML 표현식은
Elem
타입이 된다.-
Node
클래스는 모든 XML 노드 클래스의 추상 수퍼클래스다 -
Text
클래스는 텍스트를 담고 있는 노드다. -
NodeSeq
클래스는 로드의 시퀀스를 담고 있다. 각 노드를 처리할 많은 메서드는NodeSeq
를 처리하지만Node
가NodeSeq
를 상속받으므로 각 노드에서 메서드를 사용할 수 있다.
-
-
이스케이프로
{}
를 사용해서 XML 리터럴 가운데 스칼라코드를 작성할 수 있다.
scala> <a> {"hello"+", world"} </a>
-
{}
는 스칼라코드를 포함해서 XML 리터럴도 포함할 수 있으므로 스칼라코드와 XML 리터럴 사이를 오갈 수 있다.
scala> val yearMade = 1955
scala> <a>{ if (yearMade < 2000) <old>{yearMade}</old>
else xml.NodeSeq.Empty }
</a>
- 빈 노드는
xml.NodeSeq.Empty
로 나타낸다. -
<
,>
,&
는 이스케이프되서 출력된다.
scala> <a> {"<a>potential security hole<a>"} </a>
res0: scala.xml.Elem = <a> </a>potential security hole<a> </a>
##28.4 Serialization
- 데이터 구조를 XML로 변환하려면 다음과 같은
toXML
메서드를 정의한다.
abstract class Person {
val name: String
val age: Int
def toXML =
<person>
<name>{name}</name>
<age>{age}</age>
</person>
}
val p = new Person {
val name = "outsider"
val age = 25
}
p.toXML
- XML 텍스트에 중괄호를 쓰려면 2번 써준다.
scala> <a>{{{{brace yourself!}}}} </a>
res0: scala.xml.Elem = <a> {{brace yourself!}} </a>
##28.5 Taking XML apart
-
XML에서 분리해내는 메서드들이 있고 이 메서드들은 XPath 언어에 기반한다.
-
텍스트 추출 : 노드에서
text
함수를 호출한다.
scala> <a>Sounds <tag/> good</a>.text
res0: String = Sounds good
-
하위요소 추출 : 태그명으로 하위요소를 찾으려면
\ 태그명
을 호출한다.
scala> <a><b><c>hello</c></b></a> \ "b"
res0: scala.xml.NodeSeq = <b><c>hello</c></b>
- 하위의 하위요소를 찾으려면
\
대신\\
를 사용한다.
scala> <a><b><c>hello</c></b></a> \ "c"
res0: scala.xml.NodeSeq =
scala> <a><b><c>hello</c></b></a> \\ "c"
res1: scala.xml.NodeSeq = <c>hello</c>
-
속성 추출 : 요소 추출과 똑같이
\
,\\
를 사용하지만 속성명앞에@
를 사용한다.
scala> val joe = <employee name="Joe" rank="code monkey"/>
scala> joe \ "@name"
res1: scala.xml.NodeSeq = Joe
##28.6 Deserialization
- XML을 다시 데이터구조로 변환하려면 다음과 같은
fromXML
메서드를 정의한다.
def fromXML(node: scala.xml.Node): Person =
new Person {
val name = (node \ "name").text
val age = (node \ "age").text.toInt
}
##28.7 Loading and saving
- XML을 바이트의 파일로 변환하려면
XML.save
를 사용한다.
scala.xml.XML.svve("filename.xml", node)
- XML 파일을 로딩하려면
XML.loadFile
을 사용한다.
val loadnode = xml.XML.loadFile("filename.xml")
##28.8 Pattern matching on XML
- XML 패턴은 XML 리터럴처럼 보인다. 차이점은
{}
이스케이프를 사용했을 때{}
안의 코드는 표현식이 아니라 패턴이라는 점 뿐이다.{}
내에서 스칼라 패턴언어를 모두 쓸 수 있다.
def proc(node: scala.xml.Node): String =
node match {
case <a>{contents}</a> => "It's an a: " + contents
case <b>{contents}</b> => "It's an b: " + contents
case _ => "It's something else."
}
- 위 코드는 중첩태그는 처리하지 못한다. XML 노드의 시퀀스에 대한 패턴은
_*
로 작성한다.
def proc(node: scala.xml.Node): String =
node match {
case <a>{contents @ _*}</a> => "It's an a: " + contents
case <b>{contents @ _*}</b> => "It's an b: " + contents
case _ => "It's something else."
}
- XML 패턴은 for문에서도 잘 동작한다.
val catalog =
<catalog>
<cctherm>
<description>hot dog #5</description>
<yearMade>1952</yearMade>
</cctherm>
<cctherm>
<description>Sprite Boy</description>
<yearMade>1964</yearMade>
</cctherm>
catalog match {
case <catalog>{therms @ _*}</catalog> =>
for (therm <- therms)
println("processing: " + (therm \ "description").text)
}
processing:
processing: hot dog #5
processing:
processing: Sprite Boy
processing:
-
<cctherm>
요소 앞뒤로 공백이 있어서 위처럼 출력된다. 공백을 무시하려면 다음과 같이 작성한다.
catalog match {
case <catalog>{therms @ _*}</catalog> =>
for (therm @ <cctherm>{_*}</cctherm> <- therms)
println("processing: " + (therm \ "description").text)
}