캠핑과 개발

자바의 정규표현식은 J2SE 1.4 부터 지원되지 시작했습니다. 관련된 주요 클래스들는 java.util.regex 팩키지에 있습니다.

Pattern 클래스

Pattern 객체는 Perl 문법과 비슷한 형태로 정의된 정규표현식을 나타냅니다. 문자열로 정의한 정규표현식은 사용되기 전에 반드시 Pattern 클래스의 인스턴스로 컴파일되어야 합니다. 컴파일된 패턴은 Matcher 객체를 만드는 데 사용되며, Matcher 객체는 임의의 입력 문자열이 패턴에 부합되는 지 여부를 판가름하는 기능을 담당하합니다. 또한 Pattern 객체들은 비상태유지 객체들이기 때문에 여러 개의 Matcher 객체들이 공유할 수 있습니다.

Matcher 클래스

Matcher 객체는 특정한 문자열이 주어진 패턴과 일치하는가를 알아보는데 이용됩니다. Matcher 클래스의 입력값으로는 CharSequence라는 새로운 인터페이스가 사용되는데 이를 통해 다양한 형태의 입력 데이터로부터 문자 단위의 매칭 기능을 지원 받을 수 있습니다. 기본적으로 제공되는 CharSequence 객체들은 CharBuffer, String, StringBuffer 클래스가 있습니다.

Matcher 객체는 Pattern 객체의 matcher 메소드를 통해 얻어진다. Matcher 객체가 일단 만들어지면 주로 세 가지 목적으로 사용됩다.

  • 주어진 문자열 전체가 특정 패턴과 일치하는 가를 판단(matches).
  • 주어진 문자열이 특정 패턴으로 시작하는가를 판단(lookingAt).
  • 주어진 문자열에서 특정 패턴을 찾아낸다(find).

이들 메소드는 성공 시 true를 실패 시 false 를 반환합니다.

또한 특정 문자열을 찾아 새로운 문자열로 교체하는 기능도 제공됩니다. appendRepalcement 메소드는 일치하는 패턴이 나타날 때까지의 모든 문자들을 버퍼로 옮기고 찾아진 문자열 대신 교체 문자열로 채워 넣습니다. 또한 appendTail 메소드는 캐릭터 시퀀스의 현재 위치 이후의 문자들을 버퍼에 복사해 넣습니다. 다음 절에 나오는 예제 코드를 참고하도록 합시다.

CharSequence 인터페이스

CharSequence 인터페이스는 다양한 형태의 캐릭터 시퀀스에 대해 일관적인 접근 방법을 제공하기 위해 새로 생겨났으며, java.lang 패키지에 존재합니다. 기본적으로 String, StringBuffer, CharBuffer 클래스가 이를 구현하고 있으므로 적절한 것을 골라 사용하면 되며, 인터페이스가 간단하므로 필요하면 직접 이를 구현해 새로 하나 만들어도 됩니다.



자바 정규표현식 사용 예제

기본 사용 예제

소스

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 정규표현식 기본 사용 예제 
 * 
 * @author   Sehwan Noh <sehnoh at java2go.net>
 * @version  1.0 - 2006. 08. 22
 * @since    JDK 1.4
 */
public class RegExTest01 {

    public static void main(String[] args) {

        Pattern p = Pattern.compile("a*b");
        Matcher m = p.matcher("aaaaab");
        boolean b = m.matches();
        
        if (b) {
            System.out.println("match");
        } else {
            System.out.println("not match");
        }
    }
}

결과

match

문자열 치환하기

소스

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 문자열 치환 예제
 * 
 * @author   Sehwan Noh <sehnoh at java2go.net>
 * @version  1.0 - 2006. 08. 22
 * @since    JDK 1.4
 */
public class RegExTest02 {

    public static void main(String[] args) {

        Pattern p = Pattern.compile("cat");
        Matcher m = p.matcher("one cat two cats in the yard");
        
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            m.appendReplacement(sb, "dog");
        }
        m.appendTail(sb);
        System.out.println(sb.toString());
        
        // or
        //String str = m.replaceAll("dog");
        //System.out.println(str);
    }
}

결과

one dog two dogs in the yard

이메일주소 유효검사

소스

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 이메일주소 유효검사
 * 
 * @author   Sehwan Noh <sehnoh at java2go.net>
 * @version  1.0 - 2006. 08. 22
 * @since    JDK 1.4
 */
public class RegExTest03 {
    
    public static boolean isValidEmail(String email) {
        Pattern p = Pattern.compile("^(?:\\w+\\.?)*\\w+@(?:\\w+\\.)+\\w+$");
        Matcher m = p.matcher(email);
        return m.matches();
    }

    public static void main(String[] args) {
        
        String[] emails = { "test@abc.com", "a@.com", "abc@mydomain" };
        
        for (int i = 0; i < emails.length; i ++) {
            if (isValidEmail(emails[i])) {
                System.out.println(emails[i]);
            }
        }
    }
}

결과

test@abc.com

HTML 태그 제거

소스

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * HTML 태그 제거
 * 
 * @author   Sehwan Noh <sehnoh at java2go.net>
 * @version  1.0 - 2006. 08. 22
 * @since    JDK 1.4
 */
public class RegExTest04 {

    public static String stripHTML(String htmlStr) {
        Pattern p = Pattern.compile("<(?:.|\\s)*?>");
        Matcher m = p.matcher(htmlStr);
        return m.replaceAll("");
    }
    
    public static void main(String[] args) {
        String htmlStr = "<html><body><h1>Java2go.net</h1>"
            + " <p>Sehwan@Noh's Personal Workspace...</p></body></html>";
        System.out.println(stripHTML(htmlStr));        
    }
}

결과

Java2go.net Sehwan@Noh's Personal Workspace...

HTML 링크 만들기

소스

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * HTML 링크 만들기
 * 
 * @author   Sehwan Noh <sehnoh at java2go.net>
 * @version  1.0 - 2006. 08. 22
 * @since    JDK 1.4
 */
public class RegExTest05 {

    public static String linkedText(String sText) {
        Pattern p = Pattern.compile("(http|https|ftp)://[^\\s^\\.]+(\\.[^\\s^\\.]+)*");
        Matcher m = p.matcher(sText);

        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            m.appendReplacement(sb, "<a href='" + m.group()+"'>" + m.group() + "</a>");
        }
        m.appendTail(sb);

        return sb.toString();
    }    
        
    public static void main(String[] args) {        
        String strText = "My homepage URL is http://www.java2go.net/home/index.html.";
        System.out.println(linkedText(strText));
    }
}

결과

My homepage URL is <a href='http://www.java2go.net/index.html'>http://www.java2go.net/index.html</a>.

금지어 필터링하기

소스

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 금지어 필터링하기
 * 
 * @author   Sehwan Noh <sehnoh at java2go.net>
 * @version  1.0 - 2006. 08. 22
 * @since    JDK 1.4
 */
public class RegExTest06 {
    
    public static String filterText(String sText) {
        Pattern p = Pattern.compile("fuck|shit|개새끼", Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(sText);

        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            //System.out.println(m.group());
            m.appendReplacement(sb, maskWord(m.group()));
        }
        m.appendTail(sb);
        
        //System.out.println(sb.toString());
        return sb.toString();
    }
    
    public static String maskWord(String word) {
        StringBuffer buff = new StringBuffer();
        char[] ch = word.toCharArray();
        for (int i = 0; i < ch.length; i++) {
            if (i < 1) {
                buff.append(ch[i]);
            } else {
                buff.append("*");
            }
        }
        return buff.toString();
    }
    
    public static void main(String[] args) {
        String sText = "Shit! Read the fucking manual. 개새끼야.";        
        System.out.println(filterText(sText));
    }
}

결과

S***! Read the f***ing manual. 개**야.


Java Regex References

A regular expression, specified as a string, must first be compiled into an instance of this class. The resulting pattern can then be used to create a Matcher object that can match arbitrary character sequences against the regular expression. All of the state involved in performing a match resides in the matcher, so many matchers can share the same pattern.

A typical invocation sequence is thus

 Pattern p = Pattern.compile("a*b");
 Matcher m = p.matcher("aaaaab");
 boolean b = m.matches();

A matches method is defined by this class as a convenience for when a regular expression is used just once. This method compiles an expression and matches an input sequence against it in a single invocation. The statement

 boolean b = Pattern.matches("a*b", "aaaaab");
is equivalent to the three statements above, though for repeated matches it is less efficient since it does not allow the compiled pattern to be reused.

Instances of this class are immutable and are safe for use by multiple concurrent threads. Instances of the Matcher class are not safe for such use.

Summary of regular-expression constructs

ConstructMatches
 
Characters
xThe character x
\\The backslash character
\0nThe character with octal value 0n (0 <= n <= 7)
\0nnThe character with octal value 0nn (0 <= n <= 7)
\0mnnThe character with octal value 0mnn (0 <= m <= 3, 0 <= n <= 7)
\xhhThe character with hexadecimal value 0xhh
\uhhhhThe character with hexadecimal value 0xhhhh
\tThe tab character ('\u0009')
\nThe newline (line feed) character ('\u000A')
\rThe carriage-return character ('\u000D')
\fThe form-feed character ('\u000C')
\aThe alert (bell) character ('\u0007')
\eThe escape character ('\u001B')
\cxThe control character corresponding to x
 
Character classes
[abc]a, b, or c (simple class)
[^abc]Any character except a, b, or c (negation)
[a-zA-Z]a through z or A through Z, inclusive (range)
[a-d[m-p]]a through d, or m through p: [a-dm-p] (union)
[a-z&&[def]]d, e, or f (intersection)
[a-z&&[^bc]]a through z, except for b and c: [ad-z] (subtraction)
[a-z&&[^m-p]]a through z, and not m through p: [a-lq-z](subtraction)
 
Predefined character classes
.Any character (may or may not match line terminators)
\dA digit: [0-9]
\DA non-digit: [^0-9]
\sA whitespace character: [ \t\n\x0B\f\r]
\SA non-whitespace character: [^\s]
\wA word character: [a-zA-Z_0-9]
\WA non-word character: [^\w]
 
POSIX character classes (US-ASCII only)
\p{Lower}A lower-case alphabetic character: [a-z]
\p{Upper}An upper-case alphabetic character:[A-Z]
\p{ASCII}All ASCII:[\x00-\x7F]
\p{Alpha}An alphabetic character:[\p{Lower}\p{Upper}]
\p{Digit}A decimal digit: [0-9]
\p{Alnum}An alphanumeric character:[\p{Alpha}\p{Digit}]
\p{Punct}Punctuation: One of !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
\p{Graph}A visible character: [\p{Alnum}\p{Punct}]
\p{Print}A printable character: [\p{Graph}\x20]
\p{Blank}A space or a tab: [ \t]
\p{Cntrl}A control character: [\x00-\x1F\x7F]
\p{XDigit}A hexadecimal digit: [0-9a-fA-F]
\p{Space}A whitespace character: [ \t\n\x0B\f\r]
 
java.lang.Character classes (simple java character type)
\p{javaLowerCase}Equivalent to java.lang.Character.isLowerCase()
\p{javaUpperCase}Equivalent to java.lang.Character.isUpperCase()
\p{javaWhitespace}Equivalent to java.lang.Character.isWhitespace()
\p{javaMirrored}Equivalent to java.lang.Character.isMirrored()
 
Classes for Unicode blocks and categories
\p{InGreek}A character in the Greek block (simple block)
\p{Lu}An uppercase letter (simple category)
\p{Sc}A currency symbol
\P{InGreek}Any character except one in the Greek block (negation)
[\p{L}&&[^\p{Lu}]] Any letter except an uppercase letter (subtraction)
 
Boundary matchers
^The beginning of a line
$The end of a line
\bA word boundary
\BA non-word boundary
\AThe beginning of the input
\GThe end of the previous match
\ZThe end of the input but for the final terminator, if any
\zThe end of the input
 
Greedy quantifiers
X?X, once or not at all
X*X, zero or more times
X+X, one or more times
X{n}X, exactly n times
X{n,}X, at least n times
X{n,m}X, at least n but not more than m times
 
Reluctant quantifiers
X??X, once or not at all
X*?X, zero or more times
X+?X, one or more times
X{n}?X, exactly n times
X{n,}?X, at least n times
X{n,m}?X, at least n but not more than m times
 
Possessive quantifiers
X?+X, once or not at all
X*+X, zero or more times
X++X, one or more times
X{n}+X, exactly n times
X{n,}+X, at least n times
X{n,m}+X, at least n but not more than m times
 
Logical operators
XYX followed by Y
X|YEither X or Y
(X)X, as a capturing group
 
Back references
\nWhatever the nth capturing group matched
 
Quotation
\Nothing, but quotes the following character
\QNothing, but quotes all characters until \E
\ENothing, but ends quoting started by \Q
 
Special constructs (non-capturing)
(?:X)X, as a non-capturing group
(?idmsux-idmsux) Nothing, but turns match flags on - off
(?idmsux-idmsux:X)  X, as a non-capturing group with the given flags on - off
(?=X)X, via zero-width positive lookahead
(?!X)X, via zero-width negative lookahead
(?<=X)X, via zero-width positive lookbehind
(?<!X)X, via zero-width negative lookbehind
(?>X)X, as an independent, non-capturing group

Backslashes, escapes, and quoting

The backslash character ('\') serves to introduce escaped constructs, as defined in the table above, as well as to quote characters that otherwise would be interpreted as unescaped constructs. Thus the expression \\ matches a single backslash and \{ matches a left brace.

It is an error to use a backslash prior to any alphabetic character that does not denote an escaped construct; these are reserved for future extensions to the regular-expression language. A backslash may be used prior to a non-alphabetic character regardless of whether that character is part of an unescaped construct.

Backslashes within string literals in Java source code are interpreted as required by the Java Language Specification as either Unicode escapes or other character escapes. It is therefore necessary to double backslashes in string literals that represent regular expressions to protect them from interpretation by the Java bytecode compiler. The string literal "\b", for example, matches a single backspace character when interpreted as a regular expression, while "\\b" matches a word boundary. The string literal "\(hello\)" is illegal and leads to a compile-time error; in order to match the string (hello) the string literal "\\(hello\\)" must be used.

Character Classes

Character classes may appear within other character classes, and may be composed by the union operator (implicit) and the intersection operator (&&). The union operator denotes a class that contains every character that is in at least one of its operand classes. The intersection operator denotes a class that contains every character that is in both of its operand classes.

The precedence of character-class operators is as follows, from highest to lowest:

1    Literal escape    \x
2    Grouping[...]
3    Rangea-z
4    Union[a-e][i-u]
5    Intersection[a-z&&[aeiou]]

Note that a different set of metacharacters are in effect inside a character class than outside a character class. For instance, the regular expression . loses its special meaning inside a character class, while the expression - becomes a range forming metacharacter.

Line terminators

line terminator is a one- or two-character sequence that marks the end of a line of the input character sequence. The following are recognized as line terminators:

  • A newline (line feed) character ('\n'),
  • A carriage-return character followed immediately by a newline character ("\r\n"),
  • A standalone carriage-return character ('\r'),
  • A next-line character ('\u0085'),
  • A line-separator character ('\u2028'), or
  • A paragraph-separator character ('\u2029).

If UNIX_LINES mode is activated, then the only line terminators recognized are newline characters.

The regular expression . matches any character except a line terminator unless the DOTALL flag is specified.

By default, the regular expressions ^ and $ ignore line terminators and only match at the beginning and the end, respectively, of the entire input sequence. If MULTILINE mode is activated then ^ matches at the beginning of input and after any line terminator except at the end of input. When in MULTILINE mode $ matches just before a line terminator or the end of the input sequence.

Groups and capturing

Capturing groups are numbered by counting their opening parentheses from left to right. In the expression ((A)(B(C))), for example, there are four such groups:

1    ((A)(B(C)))
2    (A)
3    (B(C))
4    (C)

Group zero always stands for the entire expression.

Capturing groups are so named because, during a match, each subsequence of the input sequence that matches such a group is saved. The captured subsequence may be used later in the expression, via a back reference, and may also be retrieved from the matcher once the match operation is complete.

The captured input associated with a group is always the subsequence that the group most recently matched. If a group is evaluated a second time because of quantification then its previously-captured value, if any, will be retained if the second evaluation fails. Matching the string "aba" against the expression (a(b)?)+, for example, leaves group two set to "b". All captured input is discarded at the beginning of each match.

Groups beginning with (? are pure, non-capturing groups that do not capture text and do not count towards the group total.

Unicode support

This class is in conformance with Level 1 of Unicode Technical Standard #18: Unicode Regular Expression Guidelines, plus RL2.1 Canonical Equivalents.

Unicode escape sequences such as \u2014 in Java source code are processed as described in ?.3 of the Java Language Specification. Such escape sequences are also implemented directly by the regular-expression parser so that Unicode escapes can be used in expressions that are read from files or from the keyboard. Thus the strings "\u2014" and "\\u2014", while not equal, compile into the same pattern, which matches the character with hexadecimal value 0x2014.

Unicode blocks and categories are written with the \p and \P constructs as in Perl. \p{prop} matches if the input has the property prop, while \P{prop} does not match if the input has that property. Blocks are specified with the prefix In, as in InMongolian. Categories may be specified with the optional prefix Is: Both \p{L} and \p{IsL} denote the category of Unicode letters. Blocks and categories can be used both inside and outside of a character class.

The supported categories are those of The Unicode Standard in the version specified by the Character class. The category names are those defined in the Standard, both normative and informative. The block names supported by Pattern are the valid block names accepted and defined by UnicodeBlock.forName.

Categories that behave like the java.lang.Character boolean ismethodname methods (except for the deprecated ones) are available through the same \p{prop} syntax where the specified property has the name javamethodname.

Comparison to Perl 5

The Pattern engine performs traditional NFA-based matching with ordered alternation as occurs in Perl 5.

Perl constructs not supported by this class:

  • The conditional constructs (?{X}) and (?(condition)X|Y),

  • The embedded code constructs (?{code}) and (??{code}),

  • The embedded comment syntax (?#comment), and

  • The preprocessing operations \l \u, \L, and \U.

Constructs supported by this class but not by Perl:

  • Possessive quantifiers, which greedily match as much as they can and do not back off, even when doing so would allow the overall match to succeed.

  • Character-class union and intersection as described above.

Notable differences from Perl:

  • In Perl, \1 through \9 are always interpreted as back references; a backslash-escaped number greater than 9 is treated as a back reference if at least that many subexpressions exist, otherwise it is interpreted, if possible, as an octal escape. In this class octal escapes must always begin with a zero. In this class, \1 through \9 are always interpreted as back references, and a larger number is accepted as a back reference if at least that many subexpressions exist at that point in the regular expression, otherwise the parser will drop digits until the number is smaller or equal to the existing number of groups or it is one digit.

  • Perl uses the g flag to request a match that resumes where the last match left off. This functionality is provided implicitly by the Matcher class: Repeated invocations of the find method will resume where the last match left off, unless the matcher is reset.

  • In Perl, embedded flags at the top level of an expression affect the whole expression. In this class, embedded flags always take effect at the point at which they appear, whether they are at the top level or within a group; in the latter case, flags are restored at the end of the group just as in Perl.

  • Perl is forgiving about malformed matching constructs, as in the expression *a, as well as dangling brackets, as in the expression abc], and treats them as literals. This class also accepts dangling brackets but is strict about dangling metacharacters like +, ? and *, and will throw a PatternSyntaxException if it encounters them.



    2010/09/30 - [개발 이야기/JAVA] - JAVA를 이용한 정규식 간단 사용법


    [출처]http://www.java2go.net/java/java_regex.html


'개발 > Java' 카테고리의 다른 글

eclipse SWT/JFace 라이브러리 추가  (0) 2013.06.12
java openGL  (0) 2012.08.23
대용량 데이터 처리를 위한 JAVA Tunning(튜닝)  (0) 2012.05.17
Apache Daemon 사용하기  (0) 2012.05.17
Quartz 문서  (0) 2011.07.13

대용량 데이타를 처리할 때는 1초 아니 0.001초도 아껴야 한다.
아래의 팁을 활용하여 수행 속도를 줄여 보자.

- 64bit OS 를 사용하고, 아끼지 말고 RAM을 추가해라.
CPU만 지원한다면, 무조건 64bit 운영체제를 설치해서 사용하라. RAM이 4GB 이하라도 설치해라.
CPU의 처리 단위 증가 뿐만 아니라, 메모리를 최대한 사용할 수 있기 때문에 GC의 회수가 감소하여 속도가 더 높아진다.

내 경우, Windows XP 32bit 에서 최대메모리가 약 1.5G 이상 불가능 했는데, 
Windows7 64bit 에서는 OS가 사용하는 메모리를 제외하고 모두 JVM이 사용할 수 있었다. 
1GB 파일을 생성하는데, 대략 5~10배 정도의 실행 시간 차이가 있었다.

- xms, xmx 옵션을 최대한 크게, 그리고 같게 잡는다.
다르게 잡아 줄 경우, 실행 도중에 메모리 할당이 이루어져서 실행 시간이 증가한다.

(1) Windows7 64bit (물리적 메모리가 4g인 경우)
java -jar -xms4g -xmx4g xxx.jar  
재미있는 것은 Windows7 64bit 에서는 이 두 값을 물리적 메모리 보다 크게 잡아도 실행이 된다. 이유는 모르겠다.

(2) Windows XP 32bit (물리적 메모리가 4g인 경우)
java -jar -xms1.5g -xmx1.5g xxx.jar  
아마  1~1.5 사이까지 가능할 것이다. 넘어 가면 실행 자체가 안 되는데 실행가능한 최대값을 찾아 사용하자.

- String 대신 StringBuilder를 사용하라. (단, 스레드를 사용할 경우에는 StringBuffer를 사용하라.)
문자열에 여러 가지 조작을 가할 경우이다. 변하지 않는 문자열의 경우, String을 사용하면 된다.
String을 사용하여도 컴파일러가 적당히 변환해 준다고는 하지만, 컴파일러는 항상 개발자보다 무식하다.

참고로 실행 속도는 StringBuilder > StringBuffer >> String 이며,  
메모리사용량은 StringBuilder = StringBuffer << String 이다.
자세한 비교는 http://hongsgo.egloos.com/2033998 를 참고하라.

- String.split() 대신 StringTokenizer.nextToken()을 사용하라.
StringTokenizer.nextToken()는 사용이 불편하지만 빠르며, String.split()는 사용하기 편하지만 느리다.
token이 빈 문자열일 경우, String.split() 은 ""를 해당 배열 원소에 저장해 주지만, StringTokenizer.nextToken() 는 null을 리턴한다.
단 정규식을 구분자로 사용할 경우는 어쩔 수 없이  String.split() 을 사용해야 한다.
성능비교는  http://ir.bagesoft.com/622 를 참고하라.
 
- Buffered~계열 클래스 (BufferedReader, BufferedWriter 등) 를 사용하라.
이건 너무 쉬운 내용이라. 자세한 것은 검색을 통해 찾아 봐라.

'개발 > Java' 카테고리의 다른 글

java openGL  (0) 2012.08.23
자바 정규표현식  (0) 2012.05.17
Apache Daemon 사용하기  (0) 2012.05.17
Quartz 문서  (0) 2011.07.13
[JAVA] 동적 캐스팅  (0) 2011.06.10

1. 데몬(daemon) 이란?
 주기적인 서비스 요청을 처리하기 위해서 커널상에 백그라운드 모드로 실행되는 프로세스로, 메모리 관리 방법에 따라 단독 데몬과 xinetd로 분리된다.

단독데몬
 항상 백그라운드 모드로 실행되고 메모리를 상대적으로 많이 소비한다. 그러나 서비스(응답속도)가 빠르다. httpd와 같은 웹서비스 데몬이 대표적.
xinetd(슈퍼데몬)
 요청이 있을때마다 xinetd가 서비스를 싱행시켜주므로 메모리 소비가 적다. 그러나 단독데몬에 비해 상대적으로 서비스 속도가 느리다.


 2. 간단한 자바 데몬 만들기
 nohup을 이용해서 java를 실행시킨다.

 터미널이 종료될 때(쉘이 종료될 때) 프로세스가 죽는 이유는 해당 프로세스가 쉘의 자식 프로세스 이기 때문이다. 따라서, 부모 프로세스가 죽을대 던지는 SIGHUP을 자식 프로세스가 받게 된다.

 nohup은 부모 프로세스가 죽을때 자식 프로세스에게 SIGHUP을 던지지 않는 프로세스를 말한다.
$ nohup java 클래스명 &

  
 사용하기 편한 장점은 있으나, 문제는 중지를 시킬수 없다. 즉, 해당 프로세스 ID를 찾아내 kill하는 수 밖에 없다. 물론 파일 체크 기법, 소켓을 이용한 제어 방법등을 사용할 수 있지만 스스로 구현해야 하는 번거로움이 있다.


 3. apache commons daemon 이용하기
 Java는 UNIX의 시그널 처리를 할수 없기때문에, 중지 신호(TERM signal)를 처리하기 위해서는 따로 구현을 해야한다. 이런 번거로움을 해결하기 위해 자카르타의 하위 프로젝트중의 commons daemon을 이용한다. commons daemon은 중지 신호를 받으면 미리 지정된 메소드를 실행한다.

 ** 다운로드: http://commons.apache.org/daemon/

 UNIX용 Jsvc와 윈도우용 Procrun 있다.
 여기서는 Jsvc를 이용해보도록 하겠다.

 

 commons daemon을 다운로드해 압축을 해제하면 위 그림과 같다.
 commons-daemon.jar 파일은 Java프로젝트 lib폴더에 복사해둔다.

 


 bin폴더의 압축파일을 해제하면 jsvc-src라는 폴더가 나온다.
 폴더의 내용은 위와 같다.
 commons daemon을 사용하기 위해서는 바로 여기서 jsvc를 빌드해줘야 한다.
 빌드환경은 다음과 같다.(리눅스에서 빌드해야한다.)

GNU AutoConf(at least 2.53)
ANSI-C compliant compiler(GCC is good)
GNU Make
A Java Platform 2 compliant SDK

 여기서부터는 ubuntu 8.10 환경에서 진행하도록 한다.

 먼저 JDK가 설치되어 있지 않다면 JDK를 설치한다.
 $ sudo apt-get install sun-java6-jdk


 JDK가 설치되는 경로는 /usr/lib/jvm/java-6-sun 이다.

 gcc 및 make 가 설치되있지 않다면 아래 명령를 이용해 한방에 설치한다.
 $ sudo apt-get install build-essential


 AutoConf가 설치되있지 않다면 AutoConf를 설치한다.
 $ sudo apt-get install autoconf


 Jsvc를 빌드하는 방법은 다음과 같다.

support/buildconf.sh
./configure --with-java=/usr/lib/jvm/java-6-sun
make


참고 방법

mkdir /root/commons-daemon

cd /root/commons-daemon

wget http://www.apache.org/dist/commons/daemon/binaries/1.0.5/commons-daemon-1.0.5.jar
wget http://mirror.apache-kr.org//commons/daemon/source/commons-daemon-1.0.5-src.tar.gz
tar zxvf commons-daemon-1.0.5-src.tar.gz
cd commons-daemon-1.0.5-src/src/native/unix/
support/buildconf.sh
./configure --with-java=/opt/jdk1.6.0_24/
make
mv jsvc /root/commons-daemon

 

 빌드가 성공적으로 이루어졌다면 위 그림과 같이 jsvc가 만들어진것을 확인할 수 있다. 이후 이 파일을 가지고 Java 데몬을 실행한다.

 Java 데몬을 만들려면 org.apache.commons.daemon.Daemon 인터페이스의 init, start, stop, destory 메소드를 구현해야 한다.


샘플

package com.bagesoft.test.daemon;
 
import org.apache.commons.daemon.Daemon;
import org.apache.commons.daemon.DaemonContext;
import org.apache.commons.daemon.DaemonInitException;
 
public class TestDaemon implements Daemon, Runnable {
    private String status = "";
    private int no = 0;
    private Thread thread = null;
 
    @Override
    public void init(DaemonContext context) throws DaemonInitException,
            Exception {
        System.out.println("init...");
        String[] args = context.getArguments();
        if (args != null) {
            for (String arg : args) {
                System.out.println(arg);
            }
        }
        status = "INITED";
        this.thread = new Thread(this);
        System.out.println("init OK.");
        System.out.println();
    }
 
    @Override
    public void start() {
        System.out.println("status: " + status);
        System.out.println("start...");
        status = "STARTED";
        this.thread.start();
        System.out.println("start OK.");
        System.out.println();
    }
 
    @Override
    public void stop() throws Exception {
        System.out.println("status: " + status);
        System.out.println("stop...");
        status = "STOPED";
        this.thread.join(10);
        System.out.println("stop OK.");
        System.out.println();
    }
 
    @Override
    public void destroy() {
        System.out.println("status: " + status);
        System.out.println("destroy...");
        status = "DESTROIED";
        System.out.println("destroy OK.");
        System.out.println();
    }
 
    @Override
    public void run() {
        while (true) {
            System.out.println(no);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (no > 1000) {
                break;
            }
            no++;
        }
    }
}


init에서 초기화, start에서 처리할 작업을 별도의 쓰레드로 생성해서 실행한다. start 메소드 호출후 반드시 return 되어야 데몬이 시그널 처리를 제대로 할 수 있다.
 stop, destroy 는 중지 신호가 오면 차례되로 호출된다.


 이제 실행/중지 스크립트를 작성한다.
 Jsvc를 싱행하는데 필요한것은 실행하는 계정(user), JAVA_HOME(-home), 프로세스ID 파일(-pidfile), 출력지정(-outfile, -errfile), 클래스파일(-cp) 등이 있다.


JAVA_HOME=/opt/jdk1.6.0_24
JSVC=/root/commons-daemon/jsvc
USER=root
 
DAEMON_HOME=/root/commons-daemon
PID_FILE=$DAEMON_HOME/daemon.pid
OUT_FILE=$DAEMON_HOME/daemon.out
#ERR_FILE=$DAEMON_HOME/daemon.err
 
CLASSPATH=\
$DAEMON_HOME/commons-daemon-1.0.5.jar:\
$DAEMON_HOME/BageSoft.jar
 
MAIN_CLASS=com.bagesoft.test.daemon.TestDaemon
case "$1" in
  start)
    #
    # Start Daemon
    #
    rm -f $OUT_FILE
    $JSVC \
    -user $USER \
    -java-home $JAVA_HOME \
    -pidfile $PID_FILE \
    -outfile $OUT_FILE \
    -errfile $OUT_FILE \
    -cp $CLASSPATH \
    $MAIN_CLASS
    #
    # To get a verbose JVM
    #-verbose \
    # To get a debug of jsvc.
    #-debug \
    exit $?
    ;;
 
  stop)
    #
    # Stop Daemon
    #
    $JSVC \
    -stop \
    -nodetach \
    -java-home $JAVA_HOME \
    -pidfile $PID_FILE \
    -outfile $OUT_FILE \
    -errfile $OUT_FILE \
    -cp $CLASSPATH \
    $MAIN_CLASS
    exit $?
    ;;
 
  *)
    echo "[Usage] TestDaemon.sh start | stop"
    exit 1;;

esac 

 

이제 Java 데몬을 실행하기 위한 모든 준비를 마쳤다.

위에서 작성한 스크립트 파일을 이용해 Java 데몬을 실핸한다.
 정상적으로 데몬이 시작된다면 PID_FILE에 지정한 파일이 생성된것을 확인할 수 있다.

 

 

데몬을 중지하려면 start 대신 stop을 입력으로 스크립트를 실행하면 된다.


[출처] http://ultteky.egloos.com/10877963

'개발 > Java' 카테고리의 다른 글

자바 정규표현식  (0) 2012.05.17
대용량 데이터 처리를 위한 JAVA Tunning(튜닝)  (0) 2012.05.17
Quartz 문서  (0) 2011.07.13
[JAVA] 동적 캐스팅  (0) 2011.06.10
log4jdbc를 활용하여 쿼리 로그 남기기  (0) 2011.06.01


파일구조
#!/bin/bash

#내용

exit 0
문서의 시작은 #!bin/bash로 시작하며 문서의 끝은 exit 0으로 끝낸다.


변수선언
a=0 (O)
a = 0 (X)
b="aaaa bbbb"

변수사용
$a
$b
echo $a
$(($a + 10))


인자값(argument)

$# : 넘어온 인자의 갯수
$* : 각 인자를 나누지 않고 통틀어 참조
$@ : $*와 같지만 quoting(escape)된 문자열로 취급
$0 : 실행된 쉘스크립트 이름
$1, $2, ... 쉘, 함수 호출시 넘어온 매개변수


if문
if [표현식]; then
...
fi


if [표현식]; then
...
elif [표현식]; then
...
else
...
fi

 
test, [] :
    - test는 조건을 판별하여 0(true)/1(false)를 반환한다.
    - test는 쉘 내장명령이며, []은 이것의 또다른 표기법이다.
    - test는 보통 독립적으로 쓰이지않고, if, case, while 등의 뒤에 붙어 조건을 판별한다.

주의!!!) [ ] 은 그 사이사이를 반드시 공백으로 띄어야한다.
[ ]을 제어문자가 아닌 하나의 명령어로 이해할 것!!!

- test는 크게 다음과 같은 3가지를 판별한다.
1)스트링
2)산술식(Interger)
3)파일

- test는 다음과 같은 이진연산자를 인자로 갖는다.
A A는 true
!A A가 아니면 true
A -a B(&&) A이고 B이면 true
A -o B(||) A이거나 B이면 true

-- string 비교시 쓰이는 연산자
A == B A와 B가 같으면 true
A != B A와 B가 다르면 true
-n A A가 not null이면 true
-z A A가 null이면 true

-- integer only 연산자
A -eq B A==B
A -ne B A!=B
A -ge B A>=B
A -gt B A>B
A -le B A<=B
A -lt B A<B
*** =,>,<,!등을 써도되나 주로 스트링비교연산자로 쓰이므로
   산술비교 시는 되도록 전자의 표기법을 따라라.

-- file only 연산자
A -ef B 동일파일
A -nt B A가 최신파일(newer modification data)
A -ot B A가 오래된파일(older ..)
-e A 파일이 있다
-s A 파일크기가 0이 아님(내용있음)
-d A directory임
-f A file임
-h(or L) A Symbolic Link
-r A 현재 사용자가 r권한 갖고 있음.
-w A .. .. ..   w .. .. ..
-x A .. .. ..   x .. .. ..
-O A 내가 소유자임
-G A Group이 같음
-N A (내가) 마지막으로 읽은 후에 변경
--------여기까지만...밑에는 잘 모르겠다-------------
-S A Scoket
-p A PIPE
-b A block device(플로피,씨디롬 등 마운트객체)
-c A character special(키보드,모뎀,사운드카드등 장치)
-g A set-group-id(sgid) flag가 설정된 파일
-u A set-user-id(suid) flag가 설정된 파일
-k A has its stick bit set
-t A file descriptor가 terminal device와 관계됨.

사용법
a=하하하
b=히히히
if [ $a!=$b ]; then # [ ] 사이 공백이 있어야함에 주의!
# then을 이어서 쓸 때 앞명령과 ;로 구분함에 주의!
echo "a is not b"
else
echo "a is b"
fi

c= # 이렇게 하면 변수c는 null값을 가진다.
if [ -z $c ]; then echo "c is null"; fi

a=3
b=10
if [ $a -gt $b ]; then
echo "a is greater then b"
else
echo "a is less then b";
fi

touch 빈파일
if [ -e "빈파일" ];then echo "file is exist!"; fi
if [ -s "빈파일" ];then echo "file size is zero"; fi

case문
case $변수 in
값1 ) 처리1;;
값2 ) 처리2;;
값3 ) 처리3;;
...
* ) default처리;;
esac

ex)
case $( arch ) in
i386 ) echo 80386;; #;; 두번들어감에 유의!!!
i486 ) echo 80486;;
i586 ) echo pentium;;
i686 ) echo pentium3;;
* ) echo "몰라! 이상한 머신이야..."
esac

while문
while [ ... ];do
...
done

ex)
i=0
while [ $i -lt 10 ];do
echo $i
i=$((i+1))
sleep 0.2
done


for문
for i in 1 2 3 4 5; do
    echo $i
    sleep 0.2
done



커맨드라인(사용자) 입력받기
read
한줄로 입력하려면 aaaa<Enter> 여러줄로 입력받으려면 aaa\<Enter> bbbb\<Enter>


쉘스크립트파일안에서 쉘명령 실행
eval

ex) eval "ls -al"


문자열 제어
${...}

ex)

a=aaa하하핳BBBaaaccc

1. 문자열 길이
    echo ${#a} --> 15

2. substring
   echo ${a:3} --> aaa
   echo ${a:3:6} --> 하하하BBB : position,length

3. replace
   echo ${a//aaa/} --> 하하핳BBBccc
   echo ${a/aaa/AAA} --> AAA하하핳BBBaaaccc


파일명 비우기
 : > [파일명]


쉘에서 :은 null을 의미한다. 고로 : > [파일]은 null값을 파일에 redirection하므로 해당 파일의 크기가 0이 된다.


Tip


변수에 substring 사용하기

var=${변수명:start index:end index}


DT=`date -d +"%Y%m%d %H:%M:%S`

STR="Hello World"


month=${DT:0:5} 

str2=${STR:0:4}


echo $month

echo $str2


date 함수

현재의 날짜와 시간을 가져옴

 date  +%Y%m%d   -> 20101216

date +%y%m%d   -> 101216

등등 %Y%m%d를 변경해 가면서 사용할 수 있음

 

##하루전 날짜 구하기

date +%Y%m%d -d  '-1days'

or

date +%Y%m%d --date '1 days ago'

-- 연간 주간은 알아서 찾아 보길

 

##shell에서 사용시

$(date +"%Y%m%d")

 

##날자의 파일명 만들기

filename=exe_$(date +" %Y%m%d")

 

##date 함수 Shell에서 사용할 때

filename=exe_$(date +"%Y%m%d") //오늘 날짜

filename=exe_$(date +"%Y%m%d" -d '-1days') //전날짜




예제파일
sh1.shsh2.shsh3.shshex.sh


'개발 > Linux' 카테고리의 다른 글

linux 명령어 - yum  (0) 2012.05.17
linux 명령어 - crontab  (0) 2012.05.17
Fedora 16 | systemctl - 서비스 관리 명령어  (0) 2011.12.01
linux mysql 바이너리 버전 설치  (0) 2011.11.29
ssh 접속 설정.  (0) 2011.11.29

XSLT 빠른 가이드

개발2012. 1. 13. 10:23

XSLT Quickly 책 정리

XSLT Quickly?

XSLT를 공부하며 참고한 책인데 상당히 좋다. 예제로배우는 XSLT
책 표지

실전에서 바로 사용할만한 좋은 예제들이 가득하다. 이책을 보면서, 내용을 텍스트파일로 정리해서 XSL작업이 필요할때 바로바로 검색해서 적용하니 XSL 작성 효율이 좋아졌다. 게다가 많은 좋은 팁들이 같이 들어 있다.

XSLT Quickly 요약

★ XSL 기본 헤더와 푸터

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
...내용...
</xsl:stylesheet>

★ p.40 속성 바꾸기

<wine price="1" year="1997">Carneros</wine>
       ↓
<wine vintage="1997">Carneros</wine>

<xsl:template match="wine">
  <wine vintage="{@year}">
    <xsl:apply-template/>
  </wine>
</xsl:template>

속성이나 요소를 삭제할때는 그냥 언급을 회피하면 될뿐... @문자는 지정한 이름을 가지는 속성의 값을 의미한다.

{} 중괄호는 XSLT가 그 안의 내용을 글자 그대로 가져오지 않고 수식으로서 연산 한 뒤에 가져오도록 지정하는 것이다. {2 + 2}라고 하면 4가 들어가게 된다.

★ p.41 속성과 요소간의 변환

<wine grape="Chardonnay">
  <product>Carneros</product>
  <year>1997</year>
  <price>10.99</price>
</wine>
       ↓
<wine vintage="1997">
  <product>Carneros</product>
  <category>Chardonnay</category>
  <price>10.99</price>
</wine>

<xsl:template match="wine">
  <wine vintage="{year}">
    <product><xsl:apply-templates select="product"/></product>
    <category><xsl:value-of select="@grape"/></category>
    <price><xsl:apply-templates select="price"/></price>
  </wine>
</xsl:template>

★ p.42 속성값에 따라 요소 선택하기

어떤 요소가 특정 속성을 가질때만 선택하기

<xsl:template match="wine[@grape='Cabernet']">
  <xsl:copy><xsl:apply-templates/></xsl:copy>
</xsl:template>

★ p.50 XPath의 로케이션 스텝

child::wine[last()]
축 ::노드테스트[프레디케이트]

Axis ::NodeTest[Predicate]
필수 로케이션 스텝은 노드뿐이다. 축은 보통 생략되는 child로 간주되고 프레디케이트는 조건을 줘서 조건에 맞는 노드만을 취사 선택하는데에 사용한다. 프레디케이트는 문서의 맨위부터 따지는 것이 아니라 현재 컨텍스트 노드 자신과 가까운쪽이 1 가장 먼쪽이 last()가 된다.

★ p.50 컨텍스트(Context) 노드란?

현재 처리중인 노드를 의미한다.

★ p.51 축(Axis)?

축 한정자는 선택될 노드와 컨텍스트 노드 사이의 위치 관계를 지정한다.
종류 :

child, descendant, parent, ancester, following-sibling, preceding-sibling,
following, preceding, attribute, name-space, self, descendant-or-self, ancestor-or-self

★ p.52 부모 노드의 속성을 표시하기

<wine grape="Cabernet">
  <year>1998</year>
  <prices>
    <list>13.99</list>
    <discounted>11.99</discounted>
  </prices>
</wine>

현재 컨텍스트 노드가 prices 일때, 여기에 부모노드(<wine>)의 속성을 표시하려면,

<xsl:template match="prices">
  parent element's grape:
  <xsl:value-of select="parent::wine/attribute::grape"/>
</xsl:template>

parent와 attribute는 각각 .. 와 @ 로 축약해서 표현할 수 있다.

<xsl:template match="prices">
  parent element's grape:
  <xsl:value-of select="../@grape"/>
</xsl:template>

★ p.53 child 축의 축약형

XPath에서 축이 생략되면 무조건 child 축의 생략으로 간주한다. <wine>을 처리하는 도중 그의 자식노드인 year의 값을 가져오려면,

<xsl:template match="wine">
  <wine vintage="{child::year}">
</xsl:template>

혹은, 축 한정자가 생략되면 무조건 child로 간주하므로,

<xsl:template match="wine">
  <wine vintage="{year}">
</xsl:template>

{year}부분을 <xsl:value-of select="year"/>로 대신할 수 는 없다.

★ p.53 수식의 처리

수식을 계산하거나 어떤 노드의 값을 <xsl:value-of/>가 아닌 방법으로 얻으려면 {}사이에 넣으면 된다. {}내부에 있는 값을 계산된뒤에 입력된다.

★ p.55 ancestor 축

<A>
  <B>
    <C/>
  </B>
</A>

가 있을때 <C>의 ancestor는 <A>, <B>를 의미한다. ancester:A 와 같은 형식으로 지정하면 된다.

★ p.56 ancestor-or-self 축

<A>
  <B>
    <C/>
  </B>
</A>

가 있을때 <C>의 ancestor-or-self는 <A>,<B>,<C>이다.

★ p.56 자기 자신 혹은 자기의 부모가 가진 특정 속성의 값을 조건으로 줄때,

<xsl:template matching="waring">
  <xsl:if test="ancester-or-self::*[@xml:lang][1]/@xml:lang='en'">
    <p>Warning!</b><xsl:apply-templates/></p>
  </xsl:if>
</xsl:template>

이 경우, 아래부터 위로 검색해나간다. <C>의 위치에서 먼저 <B>를 검사하고 그 다음에 <A>를 검사하므로 만약 xml:lang 속성이 B 와 A에 있을 경우 xml:lang[1]은 B위치의 속성이 검사되게 된다. xml:lang[last]는 A위치의 속성이된다.

★ p.58 preceding-sibling / following-sibling

자기와 동일한 부모 밑에 있는 노드들 중, preceding-sibling은자기보다 위에 속한 것들이고 following-sibling은 자기보다 아래에 속한 것들이다.

<story>
  <chapter>
    <title>A</title>Contents A</chapter>
  <chapter>
    <title>B</title>Contents B</chapter>
  <chapter>
    <title>C</title>Contents C</chapter>
</story>



chapter
Prev: 
Next: B 

chapter
Prev: A
Next: C 

chapter
Prev: B
Next: 

위와 같이 하려면...

<xsl:template match="chapter">
  <h3>chapter</h3>Prev: <xsl:value-of select="preceding-sibling::chapter[1]/title"/><br/>
    Next: <xsl:value-of select="following-sibling::chapter/title"/>
    <xsl:value-of select="./text()"/><br/>
</xsl:template>

preceding-sibling이 프레디케이트를 계산할 때는 자기와 가까운 쪽, 즉 자기 바로 위를 1로 하고, 자기와 가장 먼 맨 위의 것을 last()로 한다.

★ p.61 preceding과 following

preceding 축은 문서의 처음부터 컨텍스트 노드 바로 이전까지, following은 컨텍스트 노드 바로 다음부터 문서의 끝까지의 모든 노드를 의미한다. 형제, 부모 할것 없이 다 포함한다. 프레디케이트는 자신과 가까운쪽이 1이다.

<A>
  <B>
    <C><TITLE>1</TITLE><T/></C>
    <C><TITLE>2</TITLE><D><T/></D></C>
    <C><TITLE>3</TITLE><C>
  <B>
<A>

첫번째 <T>는 <C>의 자식이고 두번째 <T>는 <D>의 자식이다. 여기서 1과 3을 얻으려면,

<xsl:template match="test">
<xsl:value-of select="preceding::C[1]/TITLE"/>
<xsl:value-of select="following::C/TITLE"/>
</xsl:template>

★ p.65 descendant와 descendant-or-self

descendant는 컨텍스트 노드의 자식들과 그 자식들의 자식들 등, 컨텍스트 노드의 모든 자식들을 의미한다. descendant-or-self는 말 그대로 자신을 포함한 자손들.

<xsl:for-each select="descendant::figure">
  <xsl:value-of select="title"/>
</xsl:for-each>

이것은 자기 아래에 있는 모든 figure 노드에서 title 요소의 값을 가져온다.

<xsl:for-each select="descendant-or-self::*/@author">
<xsl:value-of select="."/>
</xsl:for-each>

자기 자신을 포함하여 그 자식 모두를 검사하여 author 속성의 값을 출력한다.

★ p.69 descendent-or-self 의 축약

  • descendent-or-self::node() 는 // 로 표현될 수 있다.
  • chapter//title 은 chapter 요소의 자손 중에서 title이라는 이름을 가진 모든 요소를 의미한다.
  • 단지 //요소 로만 쓰이면 문서의 루트에 대한 모든 자손들을 의미한다. 예를들어 //title은 문서 전체에서 모든 title 요소를 의미한다.
  • chapter//@author 는 chapter와 그 자손들의 author 속성을 의미한다
  • chapter//comment()는 문서에 속한 모든 주석을 의미한다.

★ p.70 self

self 는 컨텍스트 노드 그 자신이다. 이것의 축약은 . 으로 self:node()를 의미한다.

★ p.70 namespace

이것은 기본 xml 네임스페이스와 컨텍스트 노드의 범위 안에 있는 모든 네임스페이스로 구성된다. (표준은 xml 네임스페이스를 포함해야 하지만 그렇지 않은 것도 있다.)

<xsl:template match="test">
  <xsl:for-each select="namespace::*">
    <xsl:value-of select="name()"/>
    <xsl:text>
    </xsl:text>
  </xsl:for-each>

★ p.72 노드 테스트(Node test)

* 은 모든 요소(Element) 노드를 의미한다. node() 는 종류에 상관없는 모든 노드를 의미한다. 이것은 주석이나 PI등도 포함한다.

<xsl:for-each selec="node()">
  <xsl:value-of select="." />
</xsl:for-each>

★ 프레디케이트(Predicate)

프레디케이트는 참/거짓의 값만 가진다.

  • child::wine[@grape] : grape 속성을 가진 모든 wine요소. grape의 값은 상관없다.
  • child::wine[year] : year 요소를 가진 wine.
  • child:wine[4] : 4번째 wine 요소. 이것은 child:wine[position() = 4]의 축약이다.
  • last() 선택된 것중 마지막 노드
  • text() 텍스트로 된 내용을 가지고 있는 모든 노드.
  • not() 조건식의 결과를 뒤집는다. not(text()), child:wine[not(@grape)]

★ p.77 손자 노드의 조건에 따라 자식 노드의 값출력

<xsl:template match="winelist">
Wines:needing their "discount" value set;
  <xsl:for-each select="wine/prices/discounted[not(text())]">
    <xsl:value-of select="../../year"/><xsl:text> </xsl:text>
    <xsl:value-of select="../../winery"/><xsl:text </xsl:text>
  </xsl:for-each>
</xsl:template>

★ p.83 동적으로 태그 생성

<xsl:element name="ode">내용</xsl:element>
이것은 <ode>내용</ode>를 생성한다.
이것을 이용해 정해지지 않은 동적 태그 생성이 가능해진다. 다음은 poem의 type 속성에 따라 동적으로 태그를 생성한다.

<xsl:template match="poem">
  <xsl:element name="{@type}">
    <author>John Milton</author>
    <year><xsl:value-of select="@year"/></year>
  </xsl:element>
</xsl:template>

★ p.84 <xsl:apply-templates>는 현재 노드의 자식 노드만을 다룬다.

이것은 자식 노드들이 <xsl:template>을 갖고 있지 않을 경우 그 노드의 값을 취해서 추가해준다. 이것을 내장 템플릿 룰이라고 한다.

★ p.86 부모, 자식, 형제의 값 얻기, 노드의 이름얻기

<xsl:template match="list">
~~~~~ Start of list element's template ~~~~~
1. List price (current node) : {<xsl:apply-templates/>}
2. Parent element (price) : {<xsl:value-of select=".."/>
3. Grandparent element contents : {<xsl:value-of select="../.."/>}
4. Attribute of grandparent : {<xsl:value-of select="../../@grape"/>}
5. Sibling node {<xsl:value-of select="../discounted"/>}
6. "Uncle" node {<xsl:value-of select="../../product"/>}
7. Parent node's name: {<xsl:value-of select="name(..)"/>}
8. Grandparent node's name: {<xsl:value-of select="name(../..)"/>}
~~~~~ End of list element's template ~~~~~
</xsl:template>

★ p.89 정해지지 않은 자기 형제 참조

<xsl:template match="item[3]">
~~~ Start of item element's template ~~~
1. This node : {<xsl:apply-templates/>}
2. First node : {<xsl:value-of select="../item[1]/>}
3. Last node : {<xsl:value-of select="../item[last()]"/>}
4. Preceding node : {<xsl:value-of select="preceding-sibling::item[1]"/>
5. Next node : {<xsl:value-of select="following-sibling::item[1]"/>}
6. flavor attriute value of first node : {<xsl:value-of select="../item[1]/@flavor"/>}
~~~ End of item element's template ~~~

xsl:value-of는 기본적으로 선택된 노드들 중 첫번째 것만 반환한다.

★ p.92 요소를 속성으로 변환하기

" " 내에 <xsl:value-of>를 쓸 수 없다. 그 대신 다음과 같이 사용한다.

<xsl:template match="wine">
  <wine variental="{@grape}" brand="{winery}" year="{../year}"/>
</xsl:template>

★ p.96 요소를 복사하며 속성 추가

<xsl:copy>가 단독으로 쓰이면 컨텍스트 노드의 요소 이름만 복사될 뿐이다. 즉, 태그만 복사되고 태그의 내용은 복사되지 않는다. 
다음은, <xsl:copy>와 다른 명령으로 속성과 내용을 복사하는 것이다.

<xsl:copy>
  <xsl:attribute name="date"> <!-- 이것이 속성을 추가해 주는 것이다. -->
    <xsl:value-of select="@date"/>
  </xsl:attribute>
  <xsl:apply-templates/> <!-- 내용복사 -->
</xsl:copy>

★ p.96 컨텍스트 노드를 자식과 속성까지 완전하게 그대로 복사하기

자식과 요소는 물론 PI와 주석, 네임스페이스 등까지 복사한다.

<xsl:template match="wine">
  <xsl:copy-of select="."/>
</xsl:template>

★ p.100 노드의 개수 세기

count() 함수를 이용한다.

<xsl:template match="employees">
  A. Number of employees:
  <xsl:value-of select="count(employee)"/>
  B. Number of officers:
  <xsl:value-of select="count(employee[@officer='yes'])"/> <!-- 'yes' 작은 따옴표! -->
  C. Number of employees without 'officer' attribute set:
  <xsl:value-of select="count(employee[not(@officer)])"/>
  D. Number of comments in 'employees' element:
  <xsl:value-of select="count(//comment())"/> <!-- 모든 주석의 개수 -->
</xsl:template>

★ p.103 apply-templates 에서 처리할 노드를 직접 지정하기

<xsl:template match="customer">
  <client>
    <xsl:apply-templates select="lastName"/>
    <xsl:apply-templates select="phone"/>
  </client>
</xsl:template>

만약 여기서 그냥 <xsl:apply-templates/>를 한다면 모든 customer의 자식 노드들의 내용이 여기에 삽입될 것이다. 여기서는 lastName과 phone에만 템플릿을 적용하여 두 자식 노드들의 값만 가져오도록 한다.

★ p.104 동일한 내용(text())를 가진 요소 제거

<sample>
  <line lid="u1">hello</line>
  <line color="red" lid="u2">hello</line>
  <line color="blue" lid="u3">hello</line>
  <line lid="u4">hello there</line>
  <line color="blue" lid="u5">hello there</line>
  <line color="blue" lid="u6">hello</line>
</sample>



<sample>
  <line lid="u1">hello</line>
  <line lid="u4">hello there</line>
</sample>

속성은 아무 관계 없이 노드의 내용이 동일한 것을 제거하려면

<xsl:template match="line">
  <xsl:if test="not(. = preceding::line)">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/> <!-- 속성과 노드의 내용 복사 -->
    </xsl:copy>
  </xsl:if>
</xsl:template>

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

★ p.105 동일한 속성을 가진 요소 제거

<xsl:template match="line">
  <xsl:if test="not(@color = preceding::line/@color)">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:if>
</xsl:template>

not(@color = preceding::line/@color) 는 컨텍스트 노드의 color 속성의 값과 현재 노드 위쪽에 존재하는 line 요소의 color 속성을 비교하여 다르면 참을 리턴한다.

★ p.106 요소와 속성을 동시에 비교하기

<xsl:template match="line">
  <xsl:variable name="contents" select="."/>
  <xsl:variable name="colorVal" select="@color"/>
  <xsl:if test = "not(preceding::line[(. = $contents) and (@color = $colorVal)])">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:if>
</xsl:template>

not(preceding::line(. = $contents) and (@color = $colorVal)]) 에서 .은 preceding::line 노드를 의미하고, @color 는 preceding::line의 color 속성을 의미한다.

★ p.109 이 노드는 비어 있는가? (text()가 없는가?)

<xsl:template match="sample">
  <xsl:choose>
    <xsl:when test="normalize-space(.)">
      Sample element <xsl:value-of select="@eid"/> isn't empty.
    </xsl:when>
    <xsl:otherwise>
      Sample element <xsl:value-of select="@eid"/> is empty.
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

normalize-space(node)는 노드 집합을 문자열로 전환한 후 여러 공백을 하나로 바꾸고, 문자열 앞뒤의 공백을 잘라낸 뒤 문자가 남아 있으면 true 그렇지 않으면 false 이다.

★ p.116 특정 자식을 갖고 있는 요소의 템플릿

<xsl:output method="text"/>
<xsl:strip-space elements="*"/>

<xsl:template match="setc2[figure]"> <!-- figure라는 자식 노드가 있는가? -->
  <xsl:value-of select="title"/>
  [<xsl:apply-templates/>]
</xsl:template>

★ p.117 노드 내용에 특정한 문자열을 포함한 요소는?

<xsl:template match="para[contains(.,'the')]"> <!-- contains()의 . 을 주의하라. -->
  ** This para has "the" in it: ***
  <xsl:apply-templates/>
</xsl:template>

문자열이 자식 노드에 포함되어 있어도 마찬가지 이다.

★ p.121 새로운 요소와 그 요소의 속성 추가하기

<xsl:template match="verse">
  <xsl:element name="line"> <!-- <line> 태그가 생성된다. -->
    <xsl:attribute name="status">done</xsl:attribute> <!-- <line status="done">
    <xsl:attribute name="hue"> 
      <xsl:value-of select="@color"/>
    </xsl:attribute> <!-- <line status="done" hue="@color의 값">
    <xsl:attribute name="number">
      <xsl:value-of select="amount"/>
    </xsl:attribute>
    <xsl:attribute name="sourceElement">
      <xsl:text>src</xsl:text><xsl:value-of select="generate-id()"/>
    </xsl:attribute>
  </xsl:element>
</xsl:template>

최종 생성 태그는 <line status="done" hue="@color" number="5" sourceElement="srcb2a"/>

★ p.124 속성의 이름과 값 얻기

<para color="blue" flavor="mint" author="bd">Here is a paragraph.</para>



Color : blue
attribute name: color
attribute value: blue
attribute name: flavor
attribute value: mint
attribute name: author
attribute value: bd

위와 같이 속성의 이름과 값을 얻으려면,

<xsl:template match="para">

Color : <xsl:value-of select="@color"/>

<!-- list the attribute names and values. -->
<xsl:for-each select="@*">
attribute name: <xsl:value-of select="name()"/>
attribute value: <xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>

★ p.126 속성의 존재 여부. 속성이 특정한 값을 가지고 있는가?

<para color="blue" flavor="mint" author="jm">Here is a paragraph.</para>



There is a flavor attribute
Athor equals "jm"
<xsl:template match="para">
  <xsl:if test="@flavor">There is a flavor attribute</xsl:if>
  <xsl:if test="@font">There is a font attribute</xsl:if>
  <xsl:if test="@author = 'jm'">Author equals "jm"</xsl:if>
</xsl:template>

★ p.127 속성 그룹(Attribute set) 사용하기

속성 그룹을 만들고 어떤 요소에 한꺼번에 추가시켜 줄 수 있다.

<xsl:attribute-set name="lineAttrs">
  <xsl:attribute name="status">done</xsl:attribute>
  <xsl:attribute name="hue">
    <xsl:value-of select="@color"/> <!-- 디폴트값. 디폴트 값은 무시될 수 있다. -->
  </xsl:attribute>
  <xsl:attribute name="number">
    <xsl:value-of select="amount"/>
  </xsl:attribute>
  <xsl:attribute name="sourceElement">
    <xsl:text>src</xsl:text><xsl:value-of select="generate-id()"/>
  </xsl:attribute>
</xsl:attribute-set>

<xsl:template match="verse">
  <xsl:element name="line" use-attribute-sets="lineAttrs">
    <xsl:attribute name="author">BD</xsl:attribute> <!-- 디폴트 값을 무시함 -->
    <xsl:attribute name="hue">NO COLOR</xsl:attribute> <!-- 디폴트 값을 무시함 -->
    </xsl:apply-templates>
  </xsl:element>
</xsl:template>

★ p.129 HTML 주석 출력하기

<xsl:template match="poem">
<html>
  <xsl:comment>Created By FabAutoDocGen release 3</xsl:comment>
  <xsl:apply-template>
</html> </xsl:template>

★ p.131 HTML 주석 사이에 노드의 값 출력하기

<xsl:template match="documentation">
  <xsl:comment><xsl:apply-templates/></xsl:comment>
</xsl:template>

★ p.131 XML파일 자체의 주석 이용하기

<xsl:template match="comment()">
  <xsl:comment><xsl:value-of select="."/></xsl:comment>
</xsl:template>

★ p.136 결과 트리에 엔티티 레퍼런스 삽입

<!DOCTYPE stylesheet [
ENTITY ntilde "n"
]>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:template match="test">
  <testOut>
    The Spanish word for "Spain" is "Espana".
    <xsl:apply-templates/>
  </testOut>
</xsl:template> </xsl:stylesheet>

스타일시트에 기본적으로 미리 선언된 다섯개의 엔티티(lt, gt, apos, quot, amp)외의 다른 엔티티를 참조하고자 한다면, 그것들을 DOCTYPE 선언부에 직접 선언해 주어야 한다.

★ p.138 엔티티 레퍼런스 자체를 삽입히기

<!DOCTYPE stylesheet [
ENTITY ntilde
"<xsl:text disable-output-escaping='yes'>n</xsl:text>"
]>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output doctype-system="testOut.dtd"/>
  <xsl:template match="test">
    <testOut>
      The Spanishword for "Spain" is "Espana"
      <xsl:apply-templates/>
    </testOut>
  </xsl:template>
</xsl:stylesheet>

Espana 가 이 모양 그대로 출력된다.

★ p.142 Namespace 지정

"xsl"을 XSLT 요소임을 나타내는 접두사로 사용하는 것은 단지 관례일 뿐이다. 다른 것을 지정해도 된다.

<harpo:stylesheet
  xmlns:harpo="http://www.w3.org/1999/XSL/Transform"
  version="1.0">
<harpo:output method="xml" omit-xml-declaration="yes"/>

<harpo:template match="xdata">
  <heading>xdata</heading><harpo:text>
  </harpo:text>
  <text><harpo:apply-templates/></text>
</harpo:template> </harpo:stylesheet>

★ p.147 XML문서를 XSLT로 변환하려면

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xslAlt="http://www.snee.com/xml/dummy"
  version="1.0">

<!-- xslAlt를 xsl로 바꿔 출력하라 -->
<xsl:namespace-alias stylesheet-prefix="xslAlt" result-prefix="xsl"/>
<xsl:template match="elementHandler">
  <!-- 아래는 <xsl:template match="@element값"> 으로 출력된다. -->
  <xslAlt:template match="{@element}">
    <xsl:apply-templates/>
  </xslAlt::template>
</xsl:template>

<xsl:template match="elementContents">
  <xslAlt:apply-templates/>
</xsl:template>
<xsl:template match="ssheet">
  <xslAlt:stylesheet version="1.0">
    <xsl:apply-templates/>
  </xslAlt:stylesheet>
</xsl:template>
<!-- Just copy any other elements, attributes, etc. -->
<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template> </xsl:stylesheet>

★ p.156 해석 불가능한 엔티티(JPG 파일등)의 URI추가

<xsl:template match="picture">
  <img src=http://img.yahoo.co.kr/blank.gif>
</xsl:template>

picfile 이 XML파일에 다음과 같이 지정되어 있다면

ENTITY ceres SYSTEM "../pics/cerespic.jpg" NDATA JPEG
생략..
<picture picfile="ceres"/>

★ p.159 PI 출력

<xsl:template match="article">
  <xsl:processing-instruction name="xml-stylesheet">
    <xsl:text>href="headlines.css" type="text/css"</xsl:text>
  </xsl:processing-instruction>
  <html>
    <xsl:apply-templates/>
  </html>
</xsl:template>

위의 결과는

<?xml-stylesheet href="headlines.css" type="text/css"?>

xsl:processing-instruction이 트리의 최상위에 위치해서는 안된다. 만약 그것이 xsl:stylesheet 요소의 자식이라면, XSLT 프로세서는 그것을 무시한다.

★ p.161 원본 트리에서 PI 읽고 이용하기

<xsl:template match="processing-instruction()">
  <xsl:copy/>
<xsl:template>

좀더 세밀하게 이용하기

<?xml-stylesheet href="headlines.css" type="text/css"?>
<?smellPlugIn scent="newCar" duration="12secs"?>

와 같은 PI가 있을 때..

<xsl:template match="processing-instruction('xml-stylesheet')">
        <stylesheet><xsl:value-of select="."/></stylesheet>
</xsl:template>

<xsl:template match="processing-instruction('smellPlugIn')">
  <smellData><xsl:value-of select="."/></smellData>
</xsl:template>

★ p.164 <xsl:if> 총정리

<xsl:template match="poem">
--- Start of "if" tests. ---
<xsl:if test="@author='jm'"> <!-- author 속성이 'jm'인가? -->
  1. The poem's author is jm.
</xsl:if>

<xsl:if test="@author"> <!-- author 속성이 존재하는가? -->
  2. The poem has an author attribute
</xsl:if>

<xsl:if test="verse"> <!-- verse 자식 요소를 가지고 있는가? -->
  4. The poem has at least one verse child element.
</xsl:if>

<xsl:if test="count(verse) > 3"> <!-- 크다. 궂이 > 를 사용안해도 됨 -->
  6. The poem has more than 3 verse child elements.
</xsl:if>

<xsl:if test="count(verse) < 3"> <!-- 작다. <를 사용하면 안되! -->
  6. The poem has less than 3 verse child elements.
</xsl:if>

<!-- or 조건주기 -->
<xsl:if test="(@author = 'bd') or (@year='1667')>
  8. Either the author is "bd" or the year is "1667".
</xsl:if>

<!-- 중첩 if -->
<xsl:if test="@year < '1850'">
  9a. The poem is old.
  
  <xsl:if test="@year < '1700'">
    9b. The poem is very old.
  </xsl:if>
  
  <xsl:if test="@year < '1500'">
    9c. The poem is very, very old.
  </xsl:if>
</xsl:if> </xsl:template>
  • 템플릿에서 test 속성의 값에 사용된 큰 따옴표 안에 "jm"이라는 문자 데이터를 보호하기 위해 따옴표를 사용한 점을 주시하자. 뿐만 아니라 스트링 값을 구분하기 위해 """ 또는 "'"라는 엔티티 참조를 대신 사용할 수 있다. (예: test="@author="jm"")
  • 만약 xsl:if 요소의 테스트 속성에서 "보다 작은(<) 부등호를 사용하려면 ">"라는 엔티티 참조를 사용해야함을 잊지 말라.
  • and/or 연산자를 사용할 수 있다.

★ p.169 <xsl:choose> 총정리

<xsl:template match="poem">
<xsl:choose>
  <xsl:when test="@year < 1638">
  The poem is one of Milton's earlier works.
  </xsl:when>

  <xsl:when test="@year < 1650">
  The poem is from Milton's middle period.
  </xsl:when>

  <xsl:when test="@year < 1668">
  The poem is one of Milton's later works.
  </xsl:when>

  <xsl:when test="@year < 1675">
  The poem is one of Milton's last works.
  </xsl:when>

  <xsl:otherwise>
  The poem was written after Milton's death
  </xsl:otherwise>
</xsl:choose> </xsl:template>

xsl:choose 는 최초로 조건을 만족시킨 부분만 실행하고 끝난다.

★ p.170 언제 중괄호{}를 사용하는가?

<xsl:template match="/">
<test>
  <xsl:variable name="myVar">10</xsl:variable>
  A. <atvtest at1="hello world"/>
  B. <atvtest at1="3 + 2 + $myVar"/> <!-- 문자열로 취급됨 -->
  C. <atvtest at1="{3 + 2 + $myVar"/> <!-- 식으로 취급됨 -->
  D. <atvtest at1="u{3+2}"/> <!-- "u5" 출력 -->
  E. <atvtest at1="yo, substring('hello world',7)"/> <!-- 문자열로 취급됨 -->
  F. <atvtest at1="yo, {substring('hello world',7)"/> <!-- "yo, world" 출력 -->
</test> </xsl:template>

★ p. 171 언제 중괄호{}를 사용하면 안되는가?

<xsl:variable name="myVar">10</xsl:variable>
A. <xsl:value-of select="3+2+$myVar"/> <!-- select 안의 내용은 수식으로 취급. {}불가 -->
B. <xsl:value-of select="substring('hello world', 7)"/>

★ p.176 <for-each>를 이용한 목차 만들기

xsl:for-each 명령은 주어진 노드들의 집합에 대하여 같은 명령을 반복적으로 실행시킨다. 이들 노드들을 명시할 때에는 XPath의 축 한정자, 노드 테스트, 프레디케이트 구문들을 그대로 사용할 수 있다.

<xsl:template match="chapter">
Pictures:
<xsl:for-each select="descendant::figure">
<xsl:value-of select="title"/><xsl:test>
</xsl:test> </xsl:for-each> Chapter:<xsl:apply-templates/> </xsl:template>

이것은 figure 요소의 title 자식요소들을 모두 가져다가 화면에 표시해준다.

★ p.177 for-each 와 XPath

xsl:tmeplate 요소의 match 속성에 XPath 표현을 사용할 수 있지만, 사실 그 XPath는 패턴이라고 알려진 XPath의 부분집합이라는 제한을 가지고 있는 반면에, xsl:for-each 요소의 select 속성에는 완벽한 XPath 표현이 가능하다.

<xsl:template match="title">
  <xsl:text>title ancestors:</xsl:text>
  <xsl:for-each select="ancestor::*">
    <xsl:value-of select="name()"/>
    <xsl:if test="position() != last()">
      <xsl:text>,</xsl:text>
    </xsl:if>
  </xsl:for-each>
</xsl:template>

<xsl:template match="para"/>

xsl:value-of 에게 어떤 노드들의 집합을 가져오게 하면 그것은 단지 그 무리에 있는 첫 번째 노드의 문자열 형식만을 던져준다는 점이다. 이에 반해 xsl:for-each는 마찬가지로 어떤 노드들의 집합을 가져오게 하면 그 집합 전체를 가져다 준다.

★ p.180 재귀 호출을 통한 템플릿 반복 수행

<xsl:template name="hyphens">
  <xsl:param name="howMany">1</xsl:param>
  <xsl:if test="$howMany > 0">

    <xsl:text>-</xsl:text>

    <xsl:call-template name="hyphens">
      <xsl:with-param name="howMany" select="$howMany - 1"/>
    </xsl:call-tempalte>
  </xsl:if>
</xsl:template>

<xsl:template match="sample">
Print 1 hyphen:
  <xsl:call-template name="hyphens"/>
    <xsl:with-param name="howMany" select="3"/>
  </xsl:call-template>

Print 20 hyphens:
  <xsl:call-template name="hyphens">
    <xsl:with-param name="howMany" select="20"/>
  </xsl:call-template>

Print 0 hyphens:
  <xsl:call-template name="hyphens">
    <xsl:with-param name="howMany" select="0"/>
  </xsl:call-tempalte>
</xsl:template>

재귀 호출에서 중요한 것은 재귀 호출을 멈출 조건이 언젠가는 반드시 참이 되어야 한다는 것이다.

★ p.184 <xsl:include> 다른 XSL 문서 포함하기

<xsl:include: href="inlines.xsl"/>

<xsl:template match="chapter">
.... 생략

inlines.xsl이 통째로 들어간 것은 아니고, 그 내용만 들어갔다. 다시 말해 그 스타일 시트의 xsl:stylesheet 태그들 사이의 모든 것들이 이 XSL내용에 끼어들어간다.

  • 포함시킨 스타일시트의 부분이 그 자체로서 하나의 완전한 스타일시트가 되어야 한다.
  • 포함 관계 중에 자기 자신이 있으면 그것은 에러이다.
  • xsl:include 요소가 top-level요소 즉, 스타일시트의 주 몸체를 만드는 xsl:stylesheet 요소의 자식 요소이면 스타일시트의 어느 곳에도 올 수 있다.

★ p.186 <xsl:import> 다른 XSL 문서 포함하기

xsl:import는 임포트 시키는 스타일시트에서 임포트된 스타일시트의 명령어들을 재정의할 수 있다. 그 외엔 xsl:include와 동일하다.

<xsl:import href="inlines.xsl"/>

xsl:import 요소는 스타일시트의 XSLT 네임스페이스에 속하는 다른 어떤 요소보다도 앞에 와야 한다.

★ p.192 이름을 가진 템플릿

템플릿에 이름을 주고 마치 함수처럼 호출 할 수 있다.

<xsl:template name="boldIt"> <!-- 템플릿에 이름을 주었다. -->
  <b><xsl:apply-templates/></b>
</xsl:template>

<xsl:template match="winery">
  <p><xsl:call-template name="boldIt"/></p> <!-- 템플릿 호출!! -->
</xsl:template>

<xsl:template match="product">
  <p><xsl:call-template name="boldIt"/></p>
</xsl:template>

<xsl:template match="year | price">
  <p><xsl:apply-templates/></p>
</xsl:template>

★ p.194 <xsl:message>를 이용한 디버깅, Debugging, 디버그

<xsl:param name="bodyTextSize">10pt</xsl:param>

<xsl:template match="/">
  <xsl:if test="$bodyTextSize != '10pt'">
    <xsl:message>bodyTextSize default value overridden with value of
      <xsl:value-of select="$bodyTextSize"/>.
    </xsl:message>
  </xsl:if>
  </xsl:appl-templates>
</xsl:template>

xsl:message 의 출력 내용은 XSLT변환의 출력으로 가지 않고 화면에 나온 다든지의 XSLT 프로세서에 따라 다르다.

★ p.196 XSLT 프로세서 실행 멈추기

<xsl:template match="/">
  <xsl:if test="not(contains($bodyTextSize, 'pt'))">
    <xsl:message terminate="yes">bodyTextSize must be specified in points
    (pt).</xsl:message>
  </xsl:if>
  <xsl:apply-templates/>
</xsl:template>

★ p.199 템플릿으로 처리하지 않고 지나쳐 버린 요소 확인하기

<xsl:template match="*">
  <h1><xsl:value-of select="name()"/> ELEMENT UNACCOUNTED
  FOR BY STYLESHEET: <xsl:apply-templates/></h1>
</xsl:template>

다른 템플릿에 의해 처리되지 않은 모든 요소들이 <xsl:template match="*">에 의해 처리된다.

★ p.209 확장 요소가 지원되는지 확인하기

XSLT 프로세서가 특정 확장 요소를 구현하지 않았다면, 프로세서는 xsl:fallback 요소의 자식 요소를 찾아 결과 트리에 붙인다.

<saxon:assing name="color">blue<xsl:fallback>
  <xsl:message>This XSLT processor doesn't support saxon:assign.
  </xsl:message></xsl:fallback>
</saxon:assing>

다른 방법으로 element-available()을 사용한다.

<xsl:choose>
  <xsl:when test="element-available('saxon:assign')">
    <saxon:assign name="color">blue</saxon:assign>
  </xsl:when>
  <xsl:otherwise>
    <xsl:message>This XSLT processor  doesn't support saxon:assign.
    </xsl:message>
  </xsl:otherwise>
</xsl:choose>

★ p.211 내장 확장 함수 사용

확장함수가 지원되는지 확인 한 뒤에 사용하기

<xsl:choose>
<xsl:when test="function-available('xalan:tokenize')">
  <xsl:for-each select="xalan:tokenize(.,',')">
    <entry><xsl:value-of select="."/></entry>
  </xsl:for-each>
</xsl:when>
</xsl:choose>

★ p.213 산술 연산 예제(숫자 계산)

<numbers>
  <x>4</x>
  <y>3.2</y>>
  <z>11</z>
</numbers>



A. 4 + 3.2 = 7.2
B. 3.2 - 4 = -0.8
C. 4 * 3.2 = 12.8
D. 11/3.2 = 3.4375
E. 4+3.2*11 = 39.2
F. (4+3.2)*11 = 79.2
G. 11 mod 4 = 3
H. 4 + 3.2 + 11 = 18.2
I. floor(3.2) = 3
J. ceiling(3.2) = 4
K. round(3.2) = 3
L. 11 + count(*) = 14
M. 3.2 + string-length("3.2") = 6.2
N. 11 + "hello" = NaN
<xsl:template match="numbers">
  A. 4 + 3.2 = <xsl:value-of select="x + y"/>
  B. 3.2 - 4 = <xsl:value-of select="y - x"/>
  C. 4 * 3.2 = <xsl:value-of select="x * y"/>
  D. 11/3.2 = <xsl:value-of select="z div y"/>
  E. 4+3.2*11 = <xsl:value-of select="x+y*z"/>
  F. (4+3.2)*11 = <xsl:value-of select="(x+y)*z"/>
  G. 11 mod 4 = <xsl:value-of select="z mod x"/>
  H. 4 + 3.2 + 11 = <xsl:value-of select="sum(*)"/>
  I. floor(3.2) = <xsl:value-of select="floor(y)"/>
  J. ceiling(3.2) = <xsl:value-of select="ceiling(y)"/>
  K. round(3.2) = <xsl:value-of select="round(y)"/>
  L. 11 + count(*) = <xsl:value-of select="11+count(*)"/>
  M. 3.2 + string-length("3.2") = <xsl:value-of select="y + string-length(y)"/>
  N. 11 + "hello" = <xsl:value-of select="z + 'hello'"/>
</xsl:template>

★ p.219 문자열 뽑아내기 함수들

<xsl:template match="verse">
  1. By itself: {<xsl:value-of select="."/>}
  2. {<xsl:value-of select="substring(.,7,6)"/>} <!-- 7번째 문자부터 6문자 -->
  3. {<xsl:value-of select="substring(.,12)"/>}
  4. {<xsl:value-of select="substring-before(.,'dreary')"/>}
  5. {<xsl:value-of select="substring-after(.,'desolation')"/>}
</xsl:template>

★ p.220 그외 문자열 함수들

<xsl:template match="verse">
  1. {<xsl:value-of select="concat('length: ', string-length(.))"/>}
  2. {<xsl:if test="contains(.,'light')"><xsl:text>light: yes!</xsl:text></xsl:if>}
  3. {<xsl:if test="starts-with(.,'Seest')">
      <xsl:text>Yes, starts with "Seest"</xsl:text>
      </xsl:if>}
  4. {<xsl:value-of select="normalize-space(.)"/>}
  5. {<xsl:value-of select="translate(.,'abcde','ABCDE')"/>}
</xsl:template>

normalize-space()는 주어진 문자열의 앞과 뒷부분에 있는 공백을 없애준다.

★ p.223 text() 사용하기

<xsl:template match="binCode">
  <productLocation>
    <row><xsl:value-of select="substring(text(), 1, 2)"/>
    </row>
    <shelf><xsl:value-of select="substring(.,3,1)"/>
    </shelf>
    <prodNum><xsl:value-of select="substring-after(text(), '-')'/>
    </prodNum>
  </productLocation>
</xsl:template>

여기서 text()와 .은 동일한 역할을 한다. text()는 주어진 컨텍스트 노드의 자식 노드인 텍스트 노드를 가리키고, "."은 substring()의 첫번째 인자로 사용되었을 때 노드의 내용을 문자열로 표현한 것을 가리킨다.

★ p.225 두 문자열의 비교

<xsl:if test=". = 'full of Pomp and Gold'">
  a = "full of Pomp and Gold"
</xsl:if>
<xsl:if test=". != ../c">
  a != ../c
</xsl:if>

두 문자열의 같은지 다른지 여부는 = 와 != 를 이용한다.

★ p.228 문자열 치환 템플릿

<xsl:template name="globalReplace">
  <xsl:param name="outputString"/>
  <xsl:param name="target"/>
  <xsl:param name="replacement"/>
  <xsl:choose>
    <xsl:when test="contains($outputString, $target)">

      <xsl:value-of select="concat(substring-before($outputString, $target), $replacement)"/>
      <xsl:call-template name="globalReplace">
        <xsl:with-param name="outputString" select="substring-after($outputString, $target)"/>
        <xsl:with-param name="target" select="$target"/>
        <xsl:with-param name="replacement" select="$replacement"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$outputString"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template match="text()">
  <xsl:call-template name="globalReplace">
    <xsl:with-param name="outputString" select="."/>
    <xsl:with-param name="target" select="'finish'"/>
    <xsl:with-param name="replacement" select="'FINISH'"/>
  </xsl:call-template>
</xsl:template>

<xsl:template match="@*|*">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

★ p.234 변수의 선언과 사용

<xsl:variable name="bodyTextSize">10pt</xsl:variable>

<xsl:template match="winery">
  <b><font size="{$bodyTextSize}"><xsl:apply-template/>
  <xsl:text> </xsl:text>
  <xsl:value-of select="../@grape"/></font><b><br/>
</xsl:template>

<xsl:template match="product">
  <i><font size="{$bodyTextSize}">
  <xsl:apply-templates/></font></i><br/>
</xsl:template>

<xsl:template match="year | price">
  <font size="{$bodyTextSize}"><xsl:apply-templates/></font><br/>
</xsl:template>

결과 트리에 반영되는 요소의 속성값이 변수나 매개변수가 가리키는 값을 넣으려고 할 때, 달러 기호가 붙은 변수가 그대로 찍히지 않게 하기 위해 위 예처럼 중괄호를 사용해야 한다. 속성이 아니라 요소의 내용에서 변수를 참조하기 위해서는 xsl:value-of 구문을 사용해야한다. 
* 변수 선언시 select 를 이용하여 동적인 값을 줄 수 있다.

<xsl:variable name="baseFontSize" select="8"/>
<xsl:variable name="bodyTextSize" select="concat($baseFontSize+2, 'pt')" />

여기서 $bodyTextSize는 '10pt' 가 된다. 
변수는 지역성을 갖는다. 동일한 이름을 갖더라도 선언 지역이 다르면 다른 변수이다.

★ p.237 변수를 사용하여 문자열을 오른쪽으로 정렬하기

<xsl:output omit-xml-declaration="yes"/>

<xsl:variable name="fieldWidth">12</xsl:variable> <!-- 12칸에 맞춰 오른쪽 정렬 -->

<xsl:template match="color">
  <xsl:variable name="valueLength" select="string-length(.)"/>
  <xsl:variable name="padding" select="$fieldWidth - $valueLength"/>
  <xsl:value-of select="substring('            ',1,$padding)"/>
  <xsl:value-of select="."/>
</xsl:template>

★ p.238 매개변수(parameter)

xsl:param 구문은 xsl:variable과 거의 같지만 한가지 차이점이 있다. 그 값은 단지 디폴트 값으로만 다루어지고, 런타임에서 재정의 될 수 있다.

<xsl:param name="bodyTextSize">10pt</xsl:param> <!-- 10pt는 런타임시 재 지정 될수 있다. -->

<xsl:template match="winery">
  <b><font size="{$bodyTextSize}"><xsl:apply-templates/>
  <xsl:text> </xsl:text>
  <xsl:value-of select="../@grape"/></font></b><br/>
</xsl:template>

지역 매개변수는 p.228 문자열 치환 템플릿 참조

★ p.248 Key(키)에 의한 검색

(키,값)의 쌍으로 정보를 구성하여 키에 의해 값을 검색하는 구조

<shirts>
  <colors>
    <color cid="c1">yellow</color>
    <color cid="c2">black</color>
    <color cid="c3">red</color>
    <color cid="c4">blue</color>
    <color cid="c5">purple</color>
    <color cid="c6">white</color>
    <color cid="c7">orange</color>
    <color cid="c7">green</color> <!-- 일부러 위와 동일하게 했슴 -->
  </colors>
  
  <shirt colorCode="c4">oxford button-down</shirt>
  <shirt colorCode="c1">poly blend, straight collar</shirt>
  <shirt colorCode="c6">monogrammed, tab collar</shirt>
</shirts>



  blue oxford button-down
  yellow poly blend, straight collar
  white monogrammed, tab collar

<color>의 @cid를 키로 이용해서 검색하면 <color>노드 자체가 리턴된다. key 검색은 검색된 노드를 반환하는 것이지 문자열(text())을 반환하는 것이 아니다.

<xsl:key name="colorNumKey" match="color" use="@cid"/> <!-- 키 생성 -->

<xsl:template match="colors"/>

<xsl:template match="shirt">
  <xsl:value-of select="key('colorNumKey', @colorCode)"/> <!-- key(키이름,키) -->
  <xsl:text> </xsl:text><xsl:apply-templates/>
</xsl:template>

또 다른 방식으로 <color>의 text()를 키로 이용하여 <color>노드 얻기

Looking up the color name with the color ID:

c3's color: red
c4's color: blue
c8's color: 
c7's color:
orange green 
Looking up the color ID with the color name:
black's cid: c2
gray's cid: 

위와 같은 결과를 얻으려면,

<xsl:output method="text"/>

<xsl:key name="colorNumKey" match="color" use="@cid"/>
<xsl:key name="colorKey" match="color" use="."/> <!-- color/text()를 키로 이용 -->

<xsl:variable name="testVar">c4</xsl:variable>
<xsl:variable name="keyName">colorKey</xsl:variable>

<xsl:template match="colors">
Looking up the color name with the color ID:

c3's color: <xsl:value-of select="key('colorNumKey', 'c3')"/>
c4's color: <xsl:value-of select="key('colorNumKey', $testVar)"/>
c8's color: <xsl:value-of select="key('colorNumKey', 'c8')"/> <!-- 존재하지 않는 키 -->
c7's color:
<xsl:for-each select="key('colorNumKey', 'c7')">
  <xsl:value-of select="."/><xsl:text> </xsl:text>
</xsl:for-each>
Looking up the color ID with the color name:
black's cid: <xsl:value-of select="key($keyName, 'black')/@cid"/>
gray's cid: <xsl:value-of select="key('colorKey', 'gray')/@cid"/>
</xsl:template>

<xsl:template match="shirt"/>

★ p.253 마지막 figure 자식 노드의 마지막 title 요소의 값 얻기

<xsl:value-of select="descendant:figure/title[last()]"/>로는 원하는 결과를 얻을 수 없다. 이 문장은 각 figure 자식노드의 마지막 title 노드를 가져온다. 
원하는 결과를 얻으려면,

<xsl:template match="chapter">
  <xsl:for-each select="descendant::figure/title">
    <xsl:if test="position() = 1"> <!-- 맨처음 figure/title만 가져옴 -->
      First figure title in chapter: <xsl:value-of select="."/>
    </xsl:if>

    <xsl:if test="position() = last()"> <!-- 맨 마지막 figure/title만 가져옴 -->
      Last figure title in chapter: <xsl:value-of select="."/>
    </xsl:if>
  </xsl:for-each>
</xsl:template>

★ p.254 알파벳 순으로 처음과 마지막 노드 얻기

<xsl:template match="chapter">
  <xsl:for-each select="descendant::figure/title">
    <xsl:sort/> 
    
    <xsl:if test="position() = 1"> <!-- 맨처음 figure/title만 가져옴 -->
      First figure title in chapter: <xsl:value-of select="."/>
    </xsl:if>

    <xsl:if test="position() = last()"> <!-- 맨 마지막 figure/title만 가져옴 -->
      Last figure title in chapter: <xsl:value-of select="."/>
    </xsl:if>
  </xsl:for-each>
</xsl:template>

★ p.255 자식 요소의 값에 따라 정렬한 뒤 맨 처음과 마지막 노드 얻기

<xsl:template match="employees">
  <xsl:for-each select="employee">
    <xsl:sort select="salary" data-type="number"/> <!-- 숫자로 간주하고 정렬하라. -->
    <xsl:if test="position() = 1">
      Lowest salary: <xsl:apply-templates/>
    </xsl:if>
  
    <xsl:if test="position() = last()">
      Highest salary: <xsl:apply-templates/>
    </xsl:if>
  </xsl:for-each>
</xsl:template>

★ p.267 HTML 형식으로 출력

XSTL 형식으로 출력되는 결과물은 Text를 제외하고 well-formed 형식을 따라야 한다. 하지만 HTML은 well-formed 태그를 제대로 인식하지 못한다. 그의 해결책으로 XSLT의 xsl:output 요가 있다. 이 요소의 method 속성에 "html" 이라고 쓰면 XSLT 프로세서는 결과물을 만들때 XHTML형식으로 만들지 않고 HTML로 만든다. 그러마 XSLT 문서 작성시에는 well-formed로 만들어야 한다.

<xsl:output method="html"/>

★ p.270 XML 파일에 자신을 처리할 XSL 지정하기

<?xml version="1.0"?>
<?xml-stylesheet href="haha.xsl" "type="text/xsl"?>
<root>
등등...

모질라 1.4, IE 6.0 에서 모두 잘 보였슴.

★ p.274 한 XSLT문서로 여러 XML 문서 처리

<xsl:output method="xml" omit-xml-declaration="yes"/>

<xsl:template match="shirts">
  <shirts>
    <!-- 여기서 xq1.xml 을 읽어서 XSLT적용 -->
    <xsl:apply-templates select="document('xq1.xml')"/>
    <xsl:apply-templates/>
  </shirts>
</xsl:template>

<xsl:tempalte match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

★ p.275 다른 XML문서의 일부 노드만 가져오기

<xsl:template match="shirts">
  <shirts>
  <!-- 속성 cid가 'c7'인것만 가저오라. -->
  <xsl:apply-templates select="document('xq1.xml')//*[@cid='c7']"/>
  <xsl:apply-templates/>
  </shirts>
</xsl:template>

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

★ p.276 다른 XML문서를 가져와 Key로 이용하기

<!-- 다른 문서 삽입. 이 문서에 <color>노드가 있다. -->
<xsl:variable name="colorLookupDoc" select="document('xq1.xsl')"/>
<xsl:key name="colorNumKey" match="color" use="@cid"/>

<xsl:template match="shirts">
  <xsl:apply-templates select="$colorLookupDoc"/>
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="colors"/>
<xsl:template match="shirts">
  <xsl:variable name="shirtColor" select="@colorCode"/>
  <xsl:for-each select="$colorLookupdoc">
    <xsl:value-of select="key('colorNumKey', $shirtColor)"/>
  </xsl:for-each>
  <xsl:text> </xsl:text><xsl:apply-templates/><xsl:txt>
  </xsl:text>
</xsl:template>

★ p.279 mode를 이용해 한 노드집합에 두 개 이상의 템플릿 정의 - 차례와 목록 만들기

<xsl:template match="story">
<html>
    <body>
  <h1>Table of Conetnts</h1>
  <xsl:apply-templates select="chapter/title" mode="toc"/>
  <xsl:apply-templates/></body></html>
</xsl:template>

<xsl:template match="chapter/title">
  <h2><a name="{generate-id()}"/><xsl:apply-templates/></h2>
</xsl:template>

<xsl:template match="chapter/title" mode="toc">
  <p><a href="#{generate-id()}"><xsl:apply-templates/></a></p>
</xsl:template>

<xsl:template match="para">
  <p><xsl:apply-templates/></p>
</xsl:template>

<xsl:template match="story/title">
  <h1><xsl:apply-templates/></h1>
</xsl:template>

★ 일반 Text 결과물 만들기

  • XSLT 프로세서로 하여금 결과 트레에 XML을 넣지 않도록 <xsl:output method="text">를 한다.
  • 혹은 <xsl:output method="xml" omit-xml-decoration="yes">
  • text로 설정하면 < 같은 것들이 자동으로 < 로 변환된다.

★ p.286 번호 붙이기(Numbering)

<!-- 일반적인 방법. 항목 앞에 숫자와 점 공백 넣기 -->
<xsl:template match="color">
  <xsl:number/>. <xsl:apply-templates/>
</xsl:template>

<!-- 숫자 형식 포맷팅 -->
<xsl:template match="colors">
  <xsl:for-each select="color">
    <xsl:number format="I. "/><xsl:value-of select="."/> <!-- I. II. III. 형식 -->
  </xsl:for-each>

  <xsl:for-each select="color">
    <xsl:number format="i. "/><xsl:value-of selet="."/> <!-- i. ii. iii. 형식 -->
  </xsl:for-each>
  
  <xsl:for-each select="color">
    <xsl:number format="A. "/><xsl:value-of select="."/> <!-- A. B. C. 형식 -->
  </xsl:for-each>

  <xsl:for-each select="color">
    <xsl:number format="a. "/><xsl:value-of select="."/> <!-- a. b. c. 형식 -->
  </xsl:for-each>
</xsl:template>

  <xsl:template match="color">
    <xsl:number format="001. "/><xsl:templates/> <!-- 001. 002. 003. 형식 -->
  </xsl:template>

xsl:number에 grouping-separator 요소의 값으로 ","를 주고 grouping-size 요소에 3을 할당하면 999를 넘는 숫자에 대해서 세 자리마다 콤마를 찍어준다.

★ p.290 multiple 넘버링

<xsl:template match="color">
  <xsl:number level="multiple" format="1. "/>
  <xsl:apply-templates/>
</xsl:template>

다음과 같은 형식의 결과를 얻게된다.

1. red
2. green
3. blue
  3.1 robin's egg
  3.2 haha
4. yellow

★ p.293 여러 단계의 노드에 대해 multiple 넘버링

<xsl:template match="chapter">
  <xsl:number format="1. "/>
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="sect1">
  <xsl:number format="1. " level="multiple" count="chapter|sect1"/>
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="sect2">
  <xsl:number format="1. " level="multiple" count="chapter|set1|sect2"/>
  <xsl:apply-templates/>
</xsl:template>

다음과 같은 형식의 결과를 얻게된다.

1.
  1.1
  1.2
2.
  2.1
    2.1.1
    2.1.2
  2.2

★ p.294 노드의 깊이에 관계 없이 문서 전체에 걸쳐 순차적인 넘버링

<xsl:template match="figure">
  <xsl:number format="1. " level="any"/><xsl:apply-templates/>
</xsl:template>

figure가 어느 노드의 자식이든지 간에 번호가 순서대로 먹여 진다.

★ p.295 노드의 깊이에 관계 없고, 특정 조상 태그마다 번호를 다시 시작하는 넘버링

<xsl:template match="figure">
  <xsl:number format="1. " level="any" from="chapter"/>
  <xsl:apply-templates/>
</xsl:template>

xsl:number 요소를 자주 사용하면 XSLT 프로세서의 속도가 떨어진다. 되도록 position()을 사용하라.

<xsl:template match="colors">
  <xsl:for-each select="color">
    <xsl:value-of select="position()"/>. <xsl:value-of select="."/>
    <xsl:text>
</xsl:text>
  </xsl:for-each>
</xsl:template>

여기서 꼭 xsl:for-each를 써야한다. 그냥 xsl:template 을 사용하면 안된다. XSLT 프로세서는 colors 요소들의 자식 요소들 중에 각 color 요소들 사이의 개행문자를 포함하고 있는 텍스트 노드까지 포함하여 각 color 요소의 위치를 계산한다.

★ p.301 숫자에 의한 정렬 / 역순 정렬

<xsl:template match="employees">
  <xsl:apply-templates>
    <xsl:sort select="salary" data-type="number" order="descending"/>
  </xsl:apply-templates>
</xsl:template>

★ p.301 다중 정렬

<xsl:template match="employees">
  <xsl:apply-templates>
    <xsl:sort select="last"/> <!-- last/first는 요소의 이름임 -->
    <xsl:sort select="first"/>
  </xsl:apply-templates>
</xsl:template>

★ p.303 속성에 의한 정렬(날짜 순)

<xsl:template match="employees">
  <xsl:apply-templates>
    <!-- hireDate는 04/23/1999 형심임 -->
    <xsl:sort select="substring(@hireDate, 7, 4)"/> <!-- year -->
    <xsl:sort select="substring(@hireDate, 1, 2)"/> <!-- month -->
    <xsl:sort select="substring(@hireDate, 3, 2)"/> <!-- day -->
  </xsl:apply-templates>
</xsl:template>

★ p.305 손자 요소에 의한 정렬

<xsl:template match="winelist">
  <xsl:copy>
    <xsl:apply-templates>
      <xsl:sort data-type="number" select="prices/discounted"/> <!-- 손자 요소를
      조거으로 -->
    </xsl:templates>
  </xsl:copy>
</xsl:template>

<xsl:template match="*"
  <xsl:copy>
    <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

xsl:sort는 xsl:for-each와 함께 쓸때 강력해진다.

★ p.313 XML문서 생성하며 Doctype 삽입

<xsl:output method="xml" doctype-system="../dtds/docbookx.dtd"
  doctype-public="-//OASIS//DTD DocBook XML//EN"/>

<xsl:template match="@*|node()">
어쩌구...

아래 문구가 삽입된다. 아래에서 chapter는 생성될 xml 문서의 root 요소이다.

<!DOCTYPE chapter
  PUBLIC "-//OASIS//DTD DocBook XML/EN" "../dtds/docbookx.dtd">

[ ] 안에 DTD 선언을 넣을 수는 없다. System 속성에 있는 외부 DTD에 모든 선언을 넣어야 한다.

★ p.315 XML 선언 넣기

<xsl:output method="xml" version="1.0" encoding="utf-8"/>

위 선언에 의해 생성된 xml 파일은 다음으로 시작된다.

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

★ p.316 XML 선언 빼기

자동으로 들어가는 선언을 빼려면..

<xsl:output method="xml" omit-xml-declaration="yes"/>

★ p.318 특정 요소가 갖고 있는 불필요한 공백을 문서 전체에 걸쳐 제거

<xsl:strip-space elements="color"/>

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

위의 스타일 시트는 원본 XML에서 color 요소의 공백을 제거하고 모든 내용을 그대로 복사한다.

★ p.320 공백 그냥 놔두기

<xsl:strip-space elements="*"/> <!-- 모든 요소의 공백을 제거하라 -->
<!-- codeListing과 sampleOutput만 빼고 -->
<xsl:preserve-space elements="codeListing sampleOutput"/>

★ p.321 들여쓰기(indentation) : xml 문서를 적당히 들여쓰기 한다.

<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>

indent="yes"에 의해 들여쓰기가 된다.

★ p.326 공백과 개행문자, Tab문자 처리

공백과 개행문자를 엔티티로 선언하면 사용하기 쉽다.

<!DOCTYPE stylesheet [
ENTITY space "<xsl:text> </xsl:text>"
ENTITY cr "<xsl:text>
</xsl:text>"
ENTITY tab "<xsl:text>  </xsl:text>"
]>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" omit-xml-declaration="yes"/>
  <xsl:template match="employee">
    <xsl:apply-templates select="@hireDate"/>&cr;
    <xsl:apply-templates select="first"/>&space;&tab; <!-- 공백과 탭 삽입 -->
    <xsl:apply-templates select="last"/>
  </xsl:template>
</xsl:stylesheet>

XML 프로세서는 요소 안에 다른 문자 데이터와 함께 개행 문자가 들어가 있으면 이를 제거하지 않는다. 일반 문자열에서 개행 문자가 작동하지 않게 하려면 <xsl:text>를 이용한다.

<xsl:text>Date</xsl:text>

★ p.334 유일한 ID 생성

<xsl:template match="chapter | sect1 | sect2">
  <xsl:copy>
    <xsl:attribute name="uid">
      <xsl:value-of select="generate-id(.)"/> <!-- ID 생성 -->
    </xsl:attribute>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

★ p.336 generate-id()를 이용한 문서내 자동 링크 생성

<xsl:output method="html"/>

<xsl:template match="chapter">
  <html>      <body      >
    <!-- Generate a list of picture titles, with each title linking to the picture in the
    poem below -->
    <b>Pictures:</b><br/>
    <xsl:for-each select="descendant::figure">
      <a href="#{generate-id(graphic)}">
      <xsl:value-of select="title"/></a><br/>
    </xsl:for-each>

    <xsl:apply-templates/>
  </body></html>
</xsl:template>

<xsl:template match="para">
  <p><xsl:apply-templates/></p>
</xsl:template>

<xsl:template match="graphic">
  <!-- 위에 각 graphic 요소마다 생성된 id와 동일한 id가 생성된다. -->
  <center><a name="{generate-id(.)}"><img src=http://img.yahoo.co.kr/blank.gif></a>
  <b><xsl:value-of select="../title"/></b></center>
</xsl:template>

<xsl:template match="figure/title"/>

</xsl:stylesheet>

★ 문서 전체를 그대로 복사하며 불필요한 노드 삭제하기

<!-- 아래는 문서 전체를 그대로 복사한다 -->
<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

<!-- 아래에 의해 불필요한 노드가 삭제된다. -->
<xsl:template match="불필요한 노드"/>
1

'개발' 카테고리의 다른 글

Git  (0) 2013.12.30
dxf file format  (0) 2012.08.16
Oracle, MSSQL, MySql 요약 설명서  (0) 2010.05.18
Maven 빌드 라이프 사이클(Lifecycle)  (0) 2009.11.19
ServerVariables 콜렉션  (0) 2009.03.10

Fedora 16에서는 서비스(Service) 관리를 systemctl이라는 명령어로 한다. (이전 버전 명령어들도 아직은 사용 가능하지만 systemctl 사용을 권장하고 있다.)


서비스 상태 확인 하기

서비스 상태 확인은 다음과 같이 한다.

systemctl status service_name.service

예를 들어 httpd의 상태를 확인하려면 다음과 같이 명령한다.

systemctl status httpd.service


서비스 시작, 중지, 재시작 하기

서비스를 시작하는 기본 명령 방식은 다음과 같다.

systemctl start service_name.service

중지할 때에는 start 대신 stop을, 재시작할 때에는 restart를 쓰면 된다. 예를 들어 httpd를 시작하려면 다음과 같이 명령한다.

systemctl start httpd.service


중지와 재시작은 다음과 같이 명령하면 된다.

systemctl stop httpd.service
systemctl restart httpd.service
systemctl start httpd.service
systemctl start vsftpd@vsftpd.service


부팅 시 자동 실행 하기

시스템 부팅 시 서비스가 자동 실행되게 하는 명령은 다음과 같다.

systemctl enable service_name.service

예를 들어 httpd를 부팅 시 자동 실행되게 하려면 다음과 같이 명령한다.

systemctl enable httpd.service

자동 실행 되지 않게 하려면 enable 대신 disable을 쓰면 된다.


실행 중인 서비스 보기

실행 중인 모든 서비스 목록을 보려면 다음과 같이 명령한다.

systemctl list-units --type=service


'개발 > Linux' 카테고리의 다른 글

linux 명령어 - crontab  (0) 2012.05.17
linux shell 스크립트  (0) 2012.01.13
linux mysql 바이너리 버전 설치  (0) 2011.11.29
ssh 접속 설정.  (0) 2011.11.29
linux 방화벽 열기  (0) 2011.11.29


## // MySQL의 default configuration 파일의 위치는 한 곳에 지정되거나
## // 어딘가에 명확히 명시되어서 실행되지 않는 것이 일반적이다.
## // 이런 경우, 현재 mysql server가 어느 위치에 있는 my.cnf 파일을 읽었는지 궁금한 경우가 많다.
## // 또한 my.cnf 파일은 RPM으로 MySQL library만 설치해도 /etc/my.cnf 파일이 생성되므로
## // mysql server가 DBA가 준비해둔 설정 파일을 읽었는지, 아니면 위처럼 의도하지 않게 
## // 생성된 my.cnf 파일을 읽고 있는지 의심이 되는 경우가 매우 허다한데, 
## // 이런 경우에는 아래와 같이 mysql server 프로세스가 기본적으로 찾게 되는 my.cnf 파일의
## // 경로를 우선순위대로 확인해볼 수 있다.

${MYSQL_HOME}/bin/mysqld --verbose --help | grep -A 1 'Default options'

Default options are read from the following fi
les in the given

'개발 > Database' 카테고리의 다른 글

index 생성  (0) 2012.05.17
Oracle Hint  (0) 2012.05.17
mysql 소스 설치  (0) 2011.11.29
ORACLE 명령문  (0) 2011.08.02
MERGE INTO 사용법  (0) 2011.07.09


http://dev.mysql.com 에서 다운로드 후 설치

mysql 5.1 바이너리 설치

[바이너리 버전 설치 순서]
shell> groupadd mysql
shell> useradd -g mysql mysql
shell> cd /usr/local
shell> gunzip < /path/to/mysql-VERSION-OS.tar.gz | tar xvf -
shell> ln -s full-path-to-mysql-VERSION-OS mysql
shell> cd mysql
shell> chown -R mysql .
shell> chgrp -R mysql .
shell> scripts/mysql_install_db --user=mysql
shell> chown -R root .
shell> chown -R mysql data
shell> bin/mysqld_safe --user=mysql &

이제 기본 데이터베이스 설치를 위해 아래의 코드 실행. script 디렉토리 안에서 mysql_install_db를 실행하니 아래와 같이 FATAL ERROR가 발생했다. 
그러므로 아래 빨간 색으로 표시된 것처럼 mysql의 탑 디렉토리에서 실행해야 성공한다.

[root@localhost bin]# cd ../scripts
[root@localhost scripts]# ls
mysql_install_db
[root@localhost scripts]# ./mysql_install_db 

FATAL ERROR: Could not find ./bin/my_print_defaults

If you compiled from source, you need to run 'make install' to
copy the software into the correct location ready for operation.

If you are using a binary release, you must either be at the top
level of the extracted archive, or pass the --basedir option
pointing to that location.

[root@localhost scripts]# pwd
/usr/local/mysql/scripts
[root@localhost scripts]# cd ..
[root@localhost mysql]# ./scripts/mysql_install_db 
Installing MySQL system tables...
090720 14:01:07 [Warning] Forcing shutdown of 2 plugins
OK
Filling help tables...
090720 14:01:07 [Warning] Forcing shutdown of 2 plugins
OK

To start mysqld at boot time you have to copy
support-files/mysql.server to the right place for your system

PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
To do so, start the server, then issue the following commands:

./bin/mysqladmin -u root password 'new-password'
./bin/mysqladmin -u root -h localhost.localdomain password 'new-password'

Alternatively you can run:
./bin/mysql_secure_installation

which will also give you the option of removing the test
databases and anonymous user created by default.  This is
strongly recommended for production servers.

See the manual for more instructions.

You can start the MySQL daemon with:
cd . ; ./bin/mysqld_safe &

You can test the MySQL daemon with mysql-test-run.pl
cd ./mysql-test ; perl mysql-test-run.pl

Please report any problems with the ./bin/mysqlbug script!

The latest information about MySQL is available at http://www.mysql.com/
Support MySQL by buying support/licenses from http://shop.mysql.com/

이제 기본 DB(mysql, test)의 설치가 끝났다. mysql 디렉토리를 보면 data라는 새 디렉토리가 생성되었을 것이다.

mysql 실행
mysql 게정으로 로긴 후
mysql]$ /usr/local/mysql/bin/mysqld_safe &

mysql 종료
mysqladmin -u root -p shutdown

root로 접속하기 (여기서 root는 시스템의 root계정이 아니라, mysql의 관리계정이다)
처음 설치시 root의 패스워드는 없다.

사용형식) mysql -u MySQL계정명 -p 접속할데이터베이스명
mysql]$ mysql -u root -p mysql

database내 테이블 조회
mysql> show tables;

테이블 스키마 조회
mysql> desc <테이블명>;


자동 시작 등록

#!/bin/sh
vi /etc/rc.d/rc.local

/usr/local/mysql/bin/mysqld_safe &

 

- 데몬이 무사히 실행됐다면 서버 시작시에 자동실행되도록 한다.
  # cp /usr/local/mysql/support-files/mysql.server /etc/rc.d/init.d
  # ln -s ../init.d/mysql.server /etc/rc.d/rc0.d/K01mysql
  # ln -s ../init.d/mysql.server /etc/rc.d/rc3.d/S90mysql

 
/var/run/mysqld/mysqld.pid를 생성하지 못할경우
cd /var/run
mkdir mysqld
chown mysql mysqld
chgrp mysql mysqld 



 

'개발 > Linux' 카테고리의 다른 글

linux shell 스크립트  (0) 2012.01.13
Fedora 16 | systemctl - 서비스 관리 명령어  (0) 2011.12.01
ssh 접속 설정.  (0) 2011.11.29
linux 방화벽 열기  (0) 2011.11.29
sftp root 계정 접속 설정  (0) 2011.07.27

ssh 접속 설정.

개발/Linux2011. 11. 29. 13:53

일단 크게

  1. ssh 관련 설정파일을 수정하고
  2. 방화벽설정을 열어준다.

정도로 접속이 가능하게 된다.
fedora12 에서 ssh 설정 관련 패키지 설정파일은 "/etc/ssh" centos는 /etc/ssh/sshd-config에 있습니다.


파일을 열어보면...

[root@localhost /]# cat /etc/ssh/sshd_config
#       $OpenBSD: sshd_config,v 1.80 2008/07/02 02:24:18 djm Exp $

# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.

# This sshd was compiled with PATH=/usr/local/bin:/bin:/usr/bin

# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options change a
# default value.

Port 8103
AddressFamily inet
ListenAddress 192.168.0.104
#ListenAddress ::

# Disable legacy (protocol version 1) support in the server for new
# installations. In future the default will change to require explicit
# activation of protocol 1
Protocol 2

# HostKey for protocol version 1
#HostKey /etc/ssh/ssh_host_key
# HostKeys for protocol version 2
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key

# Lifetime and size of ephemeral version 1 server key
#KeyRegenerationInterval 1h
#ServerKeyBits 1024

# Logging
# obsoletes QuietMode and FascistLogging
#SyslogFacility AUTH
SyslogFacility AUTHPRIV
LogLevel INFO

# Authentication:

#LoginGraceTime 2m
PermitRootLogin no
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

#RSAAuthentication yes
#PubkeyAuthentication yes
#AuthorizedKeysFile     .ssh/authorized_keys

# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#RhostsRSAAuthentication no
# similar for protocol version 2
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# RhostsRSAAuthentication and HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes

# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
PasswordAuthentication yes

# Change to no to disable s/key passwords
#ChallengeResponseAuthentication yes
ChallengeResponseAuthentication no

# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no

# GSSAPI options
#GSSAPIAuthentication no
GSSAPIAuthentication yes
#GSSAPICleanupCredentials yes
GSSAPICleanupCredentials yes

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
#UsePAM no
UsePAM yes

# Accept locale-related environment variables
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS

#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
#X11Forwarding no
X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
#UsePrivilegeSeparation yes
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#ShowPatchLevel no
#UseDNS yes
#PidFile /var/run/sshd.pid
#MaxStartups 10
#PermitTunnel no
#ChrootDirectory none

# no default banner path
#Banner none

# override default of no subsystems
Subsystem       sftp    /usr/libexec/openssh/sftp-server

# Example of overriding settings on a per-user basis
#Match User anoncvs
#       X11Forwarding no
#       AllowTcpForwarding no
#       ForceCommand cvs server
[root@localhost /]#


파일에서 vi 에디터로  주황색으로 표시된부분만 수정해준다. (위 내용은 현재 사용하고있는 테스트 서버의 내용)

Port 8103 는 Listen 포트를 변경하는 부분... 기본값은 22

포트를 변경하였을때에는 /etc/services 파일과 방화벽에서 해당포트를 열어주어야한다. (여기서는 8103)

AddressFamily inet 는 ipv4, ipv6 에 대한 옵션이라고함. inet 으로 설정하면 ipv4 에 대해서만 bind 한다고함.

ListenAddress 192.168.0.104는 Listen 할 아이피를 설정해주는 부분.
SyslogFacility AUTHPRIV   로그에대한 옵션임 로그파일이 저장되는 곳을 지정. AUTHPRIV 가 기본값. 기본값일때에는
/var/log/secure 에 로그를 기록하게됨.

LogLevel INFO 로그레벨은 Info 로 지정함으로써 왠만한 기록은 다 기록된다고 함.

PermitRootLogin no 는 ssh 접속시 루트 계정으로 접속을 허용하느냐 마느냐 임...


특정 계정만 ssh 접속을 허용하는 경우

#LoginGraceTime 2m
PermitRootLogin no
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
AllowUsers admin guest test1 test2




이제 ssh 데몬을 재시작한다.

[root@localhost /]# /etc/init.d/sshd restart
sshd 를 정지 중:                                           [  OK  ]
sshd (을)를 시작합니다:                                    [  OK  ]
[root@localhost /]#


방화벽이 꺼져있는 상태이고, 포트가 기본인 22로 설정 되어있을경우에는 여기까지하면 완료가된다.

참고로...

ssh 버전확인은...
[root@localhost /]# rpm -qa | grep ssh
openssh-clients-5.2p1-31.fc12.i686
openssh-server-5.2p1-31.fc12.i686
trilead-ssh2-213-6.fc12.i686
openssh-5.2p1-31.fc12.i686
libssh2-1.2-2.fc12.i686
openssh-askpass-5.2p1-31.fc12.i686
[root@localhost /]#


ssh 상태보기는...
[root@localhost /]# /etc/init.d/sshd status
openssh-daemon (pid  7931)를 실행하고 있습니다..
[root@localhost /]#




자... 이제 /etc/services 파일과 방화벽에서 해당포트를 열어주는 작업을 해주자.

ssh             8103/tcp                          # The Secure Shell (SSH) Protocol

ssh 에 관한 부분에서 포트번호를 바꾸어준다.


그리고 방화벽 파일을 변경하여 포트를 열어주자

[root@localhost /]# cat /etc/sysconfig/iptables
# Firewall configuration written by system-config-firewall
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 8103 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
[root@localhost /]#


이렇게 해주면...

ssh 프로그램으로 원격접속이 가능하게 된다.

참고로...

방화벽 상태 알아보기
/sbin/service iptables status

방화벽 올리고 내리기
/sbin/service iptables stop
/sbin/service iptables start


[출처] http://pippen80.cafe24.com/255



'개발 > Linux' 카테고리의 다른 글

Fedora 16 | systemctl - 서비스 관리 명령어  (0) 2011.12.01
linux mysql 바이너리 버전 설치  (0) 2011.11.29
linux 방화벽 열기  (0) 2011.11.29
sftp root 계정 접속 설정  (0) 2011.07.27
linux 명령어 - nohup  (0) 2011.07.21

ex ) 8080 포트 열기
[root@blogserver bin]# vi /etc/sysconfig/iptables

# Firewall configuration written by system-config-firewall
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT

-A INPUT -m state --state NEW -m tcp -p tcp --dport 8103 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 21 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT

-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT



[root@blogserver bin]#
[root@blogserver bin]# /etc/init.d/iptables restart
iptables: 방화벽 규칙을 지웁니다: [  OK  ]
iptables: chain을 ACCEPT 규칙으로 설정 중:  filter [  OK  ]
iptables: 모듈을 언로드하는 중: [  OK  ]
iptables: 방화벽 규칙 적용 중:  [  OK  ]
[root@blogserver bin]#
[root@blogserver bin]# /etc/init.d/iptables status
테이블: filter
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination        
1    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
2    ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0          
3    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0          
4    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:8103
5    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:3306
6    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:21
7    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:8080 
8    REJECT     all  --  0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination        
1    REJECT     all  --  0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination        

[root@blogserver bin]#



방화벽 상태 알아보기
/sbin/service iptables status

방화벽 올리고 내리기
/sbin/service iptables stop
/sbin/service iptables start


특정 아이피 막기
iptables -A INPUT -s xx.xx.xx.xx -j DROP

특정 아이피 해제
iptables -D INPUT -s xx.xx.xx.xx -j DROP

특정 IP  웹  접속 차단
iptables -A INPUT -s xx.xx.xx.xx -p tcp --dport 80 -j DROP


해당 C class 웹 접속 차단
iptables -A INPUT -s 210.221.204.0/24 -p tcp --dport 80 -j DROP



[출처] http://pippen80.cafe24.com/271


'개발 > Linux' 카테고리의 다른 글

linux mysql 바이너리 버전 설치  (0) 2011.11.29
ssh 접속 설정.  (0) 2011.11.29
sftp root 계정 접속 설정  (0) 2011.07.27
linux 명령어 - nohup  (0) 2011.07.21
Linux IP 변경  (0) 2011.07.21