xalan 에서 이용할 xsl 템플릿을 만들고 싶습니다.

vudghkzm의 이미지

다음과 같은 형태의 xml 문자열을 만들수 있는 xls 템플릿을 만들고자 합니다.

<?xml version="1.0"?>
<doc>
    <result>
        <key name="success">
            <value>false</value>
        </key>
        <key name="code">
            <value>100</value>
        </key>
        <key name="errorMsg">
            <value>some error occur</value>
        </key>
    </result>

    <result>
        <key name="success">
            <value>true</value>
        </key>
        <key name="people">
            <value>Tom</value>
            <value>Bill</value>
            <value>Kevin</value>
        </key>
    </result>
</doc>

위와 같은 형태의 xml 을 쉽게 만들 수 있도록 xsl 파일을 정의하고자 합니다.

규칙은 다음과 같습니다.
우선 <doc>와 </doc> 안에는 <result></result> 가 0개 이상 존재할 수 있습니다. <result></result> 안의 <key></key> 도 0개 이상 존재할 수 있습니다. 그리고 <key> 에는 name 이라는 속성이 있고, 이 name 속성의 값은 패러미터로 넘겨주는 값이 들어가게 하고 싶습니다. 마지막으로 <key></key> 안의 <value></value>는 0개 이상 존재할 수 있도록 하고 싶고, <value>와 </value> 사이에 들어갈 값은 패러미터로 넘겨주고 싶습니다.

아이디 atie 분께서 소개해주신 xalan 에 보니까 UseStylesheetParam 이라는 샘플이 있더군요. xsl 파일에 parameter를 두어서 parameter 값에 따라 출력되는 xml 이 생성되는..일종의 템플릿과 같은 것 말이죠. 바로 제가 하고자 하는 것과 같은 것이죠. 그런데 문제는 이 예제가 너무 간단하다는 것입니다.

몇개의 <result> 엘레멘트가 생길지, 몇개의 <key> 엘레멘트가 생길지, 몇개의 <value> 엘레멘트가 생길지는 동적으로 결정됩니다. 이와 같은 경우 어떤식으로 xsl 을 작성하면 되나요?

궁금합니다.

atie의 이미지

result와 같이 반복이 되는 것은 xsl:for-each를 쓰시면 됩니다. 절대 경로로 적으면 다음이 되겠고요.

<xsl:for-each select="/doc/result">
...
</xsl:for-each>

key처럼 name이라는 속성값을 갖는 것은 /doc/result/key[@name="code"] 같이해서 구분을 하여 분기문을 만들고, value는 그 분기문들 내에서 xsl:for-each를 다시 써서 가져오면 될 듯 하네요.
직접 해 보신 후에 안되면 다시 질문을 해주세요 그 때는 저도 한번 테스트를 해 보겠습니다.

그리고, 이것을 프린트 해두고 옆에 두면 두고두고 유용합니다.

//다시 읽어보니 xml을 생성을 하는 것이군요. 그렇다면, xsl:for-each 안에서 xsl:call-template을 부르면 됩니다. value를 예를 들어

<xsl:for-each select="/doc/result/key[@name="people"]>
    <xsl:call-template name="PEOPLE_NAME">
</xsl:for-each>
<xsl:template name="PEOPLE_NAME">
    <xsl:param name="NAME"/>
    <value><xsl:value-of select="$NAME"/></value>
</xsl:template>

----
I paint objects as I think them, not as I see them.
atie's minipage

atie의 이미지

반가운 질문인지라 참고 삼아 글 하나 더 적습니다.

위의 예에서 그럼 param은 어떻게 가져오나가 다음 질문인데,

갯수가 적은 경우는 자바 코드상에서 직접 패싱을 하고

Transformer transformer = TEMPLATES.newTransformer();
transformer.setParameter("NAME", "atie");

또는, getter/setter 클래스라면, 클래스를 namespace에 등록을 하고
getName()등의 method를 이용해서 가져와도 되고,

아니면, 데이타베이스에서 직접 읽어오는 것은 xalan의 sql 확장 기능을
사용하여 가져와도 됩니다. select문으로 읽어오는 것은 데이타베이스 connection에
필요한 정보만 template에 넘겨준 후 쉽게 처리를 할 수 있죠.

----
I paint objects as I think them, not as I see them.
atie's minipage

vudghkzm의 이미지

먼저 답변 감사드립니다.

답변을 보고 곧바로 xsl 을 만들고 테스트를 해보았습니다. 우선은

<doc>
    <result>
    1
    </result>
    <result>
    2
    </result>   
</doc>

위와 같이 <doc> 안에 <result>를 for-each 로 2개 찍는 것을 시도해 보았습니다.

작성한 test.xsl 은 다음과 같습니다.

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
    <doc>
        <xsl:call-template name="results"/>
    </doc>
</xsl:template>

<xsl:template name="results">
    <xsl:param name="param"/>
    <xsl:for-each select="/doc">
        <result><xsl:value-of select="$param"/></result>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

그리고 작성한 자바 코드는 다음과 같습니다.

class Test {
    public static void main(String args[]) throws Exception {
        TransformerFactory transFactory = TransformerFactory.newInstance();
        Templates aTemplate = transFactory.newTemplates(new StreamSource("test.xsl"));
        Transformer transformer = aTemplate.newTransformer();
        transformer.setParameter("param", "1");
        transformer.setParameter("param", "2");
        transformer.transform(new StreamSource("test.xsl"), new StreamResult(new OutputStreamWriter(System.out)));
    }
}

컴파일 후 실행을 하니 다음과 같이 결과가 나오더군요.

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

아직 내공이 굉장히 부족해서 그런지 xsl 작성에 대해서 모르는 부분과 이해가지 않는 부분이 많네요.

위에서 부탁드렸던 xml 파일을 만들 수 있는 xsl 템플릿 파일을 직접 만드셔서 예제로 보여주시면 이해가 쉽게 될거 같습니다.

또 궁금한것은 attribute 가 없는 태그는 <result></result> 와 같이 그냥 찍으면 되는데, attribute 가 있는 태그는 어떻게 찍어야 하나요? 예를 들어, 이번에 <key> 태그는 name 이라는 속성이 있는데...

<key name="<xsl:value-of select "$parameter">"></key> 

이런식으로 하면 되는것인가요?

제 생각에 분명히 xml 을 작성하는 것은 굉장히 많은 어플리케이션 프로그램에서 필요할 거라고 생각합니다. 그리고 제 생각에 가장 쉽게 xml 을 새로 만드는 방법이 템플릿을 만들어놓고, 템플릿에 정의된 패러미터에 값을 전달해서 xml 을 새로 만드는 것이라고 생각을 했는데요.. 그래서 검색 엔진에서 검색을 하면 예제가 쉽게 나올줄 알았는데... 그런 예제는 정말 찾기 힘드네요. ㅠ.ㅠ
거의 다 객체를 xml 로 바인딩해서 xml 파일 혹은 xml 문자열을 새로 만들더군요.. 실제로 이 방법이 최근에 유행하는 방법인가요?
이쪽 분야에는 모르는게 많아서(다른것도 많이 모르지만 -_-) 도통 감이 잘 안오네요..

한 수 가르침 부탁드립니다.

M.W.Park의 이미지

일단, 테스트 없이 예상으로 글을 올립니다.
xsl:call-template을 하실때 with-param이 빠진것같습니다.

그리고, attribute쪽은

<xsl:element name="elemName">
    <xsl:attribute name="attr1">value1</xsl:attribute>
    Text
</xsl:element>

로 하시면
<elemName attr1="value1">Text</elemName>
의 결과를 얻으실 수 있습니다.

-----
오늘 의 취미는 끝없는, 끝없는 인내다. 1973 法頂

byung82의 이미지

다음과 같으 수정해보시기 바랍니다

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
    <doc>
        <xsl:apply-templates select="result" />
    </doc>
</xsl:template>

<xsl:template match="result">
        <result><xsl:value-of select="."/></result>
</xsl:template>
</xsl:stylesheet>

자바는 제가 모르기 때문에 패스 ^^:

이렇게 한번 해보시기 바랍니다.

atie의 이미지

우선 transformer 동작 원리만 설명을 드리게 위해 간단한 예제로 설명을 합니다.

다음의 xml을 화면상에 출력하고자 합니다.

<?xml version="1.0" encoding="UTF-8"?>
<doc>
<result>1</result>
<result>2</result>
</doc>

XSL(test.xsl)은 이렇습니다.

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="VAL1"/>
<xsl:param name="VAL2"/>
<xsl:template match="/">
	<doc>
		<result><xsl:value-of select="$VAL1"/></result>
		<result><xsl:value-of select="$VAL2"/></result>
	</doc>	
</xsl:template>
</xsl:stylesheet>

자바 코드는 이렇습니다.

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public class XSLTTest {

	public XSLTTest() throws TransformerException, IOException  {
		TransformerFactory transFactory = TransformerFactory.newInstance();
		Templates aTemplate = transFactory.newTemplates(new StreamSource(System
				.getProperty("ROOT")
				+ File.separator + "test.xsl"));
		Transformer transformer = aTemplate.newTransformer();
		transformer.setParameter("VAL1", 1);
		transformer.setParameter("VAL2", 2);
		transformer.transform(new StreamSource(getFakeSource()),
				new StreamResult(new OutputStreamWriter(System.out)));
	}

	private File getFakeSource() throws IOException {
		byte[] b = new String(
				"<?xml version=\"1.0\"?><FAKESOURCE>"
				+ "</FAKESOURCE>").getBytes();
		File backDir = new File("backdir");
		File buf = File.createTempFile("DOC", ".xml", backDir);
		FileOutputStream fos = new FileOutputStream(buf);
		fos.write(b);
		fos.flush();
		fos.close();
		return buf;
	}

	public static void main(String args[]) {
		try {
			@SuppressWarnings("unused")
			XSLTTest xt = new XSLTTest();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

transform의 소스는 xml 파일이여야 하기 때문에, getFakeSource()에서 스트링 오브젝트로 간단히 xml을 만들어서 파일 변환을 한 후에 넘겨주는 것에 주목을 하시길 바랍니다. (직접 해보신 위의 설명으로는 xsl 소스를 넘겼기에 아무 결과를 못 보셨을 터입니다.)
실행은 -DROOT=/home/mydirectory (자바 코드가 실행이 되는 디렉토리)를 시스템 argument로 주고, 그 디렉토리 밑에 backdir (buf가 DOC9999.xml하는 식으로 저장이 됩니다)을 미리 만들어 놓고 합니다.

질문하신 동적으로 array를 parameter로 넘기거나 혹은 다른 방법으로 처리하는 것은 저도 테스트를 한 후에 답변을 드리겠습니다. xsl:for-each를 위해 DB table의 row/col만 읽어서 처리를 하였는지라, array object가 nodelist로 변환이 되는지가 xalan으로만 가능한지 아니면 extension을 만들어야 하는지 테스트를 해 보아야 알겠습니다.

----
I paint objects as I think them, not as I see them.
atie's minipage

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.