2009년 9월 29일 화요일

java.sql.DatabaseMetaDataを使うとDBのメタ情報

やまろうのJavaなわけ
                     2006/01
Vol.44 java.sql.DatabaseMetaDataでDBメタ情報からSQLを自動生成する

java.sql.DatabaseMetaDataを使うとDBのメタ情報(テーブル定義情報等)を
取得することが出来ます。テーブル名や列名、属性、長さ等です。
これらを元にSQL文を生成したいと思います。
                                                                */
package tool.db; import java.io.FileWriter; import java.io.PrintWriter; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; /** * JDBCでDBに接続してメタ情報を取得し、SQL文を生成してファイルに出力する。 * SQL文はSELECT(無条件 & 主キーを条件)、INSERT、UPDATE(主キーを条件)、 * DELETE(主キーを条件) * @author yamarou */ public class SQLGeneretor { public static void main(String[] args) throws Exception { System.out.println("処理開始"); PrintWriter out = new PrintWriter(new FileWriter("c:/TEMP/sql.txt")); String driverName = "COM.ibm.db2.jdbc.app.DB2Driver"; String url = "jdbc:db2:YAMAROUDB"; String user = "db2admin"; String password = "db2admin"; String schem = "SCHEM01"; ArrayList list = loadDBInfo(driverName, url, user, password, schem); for (int i = 0; i < list.size(); i++) { TableVO table = (TableVO) list.get(i); String tableID4Java = table.getName(); tableID4Java = tableID4Java.substring(0, 1) + tableID4Java.substring(1).toLowerCase(); String sql = "SELECT "; String columnNames = ""; for (Iterator iter = table.getColumns().iterator(); iter.hasNext(); ) { String column = (String) iter.next(); sql += column + ","; columnNames += column + ","; } sql = sql.substring(0, sql.length() - 1); sql += " FROM " + schem + "." + table.getName(); columnNames = columnNames.substring(0, columnNames.length() - 1); sql += " WHERE "; String where = ""; for (Iterator iter = table.getPrimaryKeys().iterator(); iter.hasNext(); ) { String column = (String) iter.next(); sql += column + "=? AND "; where += column + "=? AND "; } sql = sql.substring(0, sql.length() - 5); out.println(sql); try { where = where.substring(0, where.length() - 5); } catch (StringIndexOutOfBoundsException e) { } sql = "INSERT INTO " + schem + "." + table.getName() + "("; for (Iterator iter = table.getColumns().iterator(); iter.hasNext(); ) { String column = (String) iter.next(); sql += column + ","; } sql = sql.substring(0, sql.length() - 1); sql += ") VALUES("; String values = ""; for (Iterator iter = table.getColumns().iterator(); iter.hasNext(); ) { String column = (String) iter.next(); sql += "?,"; if (column.equals("RCRD_CRTS")) { values += "CURRENT TIMESTAMP,"; } else if (column.equals("ROW_UPDTS_DBS")) { values += "CURRENT TIMESTAMP,"; } else { values += "?,"; } } sql = sql.substring(0, sql.length() - 1) + ")"; out.println(sql); values = values.substring(0, values.length() - 1); sql = "DELETE FROM " + schem + "." + table.getName() + " WHERE "; for (Iterator iter = table.getPrimaryKeys().iterator(); iter.hasNext(); ) { String column = (String) iter.next(); sql += column + "=? AND "; } sql = sql.substring(0, sql.length() - 5); out.println(sql); sql = "UPDATE " + schem + "." + table.getName() + " SET "; String columnNamesAndParameters = ""; for (Iterator iter = table.getColumns().iterator(); iter.hasNext(); ) { String column = (String) iter.next(); sql += column + "=?,"; if (column.equals("ROW_UPDTS_DBS")) { columnNamesAndParameters += column + "=CURRENT TIMESTAMP,"; } else if ( column.equals("RCRD_CRTS") || column.equals("CREAT_USRID_RCRD") || column.equals("DEL_FLAG")) { } else { columnNamesAndParameters += column + "=?,"; } } columnNamesAndParameters = columnNamesAndParameters.substring( 0, columnNamesAndParameters.length() - 1); sql = sql.substring(0, sql.length() - 1) + " WHERE "; for (Iterator iter = table.getPrimaryKeys().iterator(); iter.hasNext(); ) { String column = (String) iter.next(); sql += column + "=? AND "; } sql = sql.substring(0, sql.length() - 5); out.println(sql); } out.close(); System.out.println("処理終了"); } /** * DB情報を取得してリストに格納して返す。 * @param driverName ドライバー名 * @param url URL * @param user DBユーザ名 * @param password DBパスワード * @param schem DBスキーマ名 * @return DB情報 * @throws ClassNotFoundException ドライバークラスが見つからない * @throws SQLException DBエラー */ public static ArrayList loadDBInfo( String driverName, String url, String user, String password, String schem) throws ClassNotFoundException, SQLException { Class.forName(driverName); Connection con = DriverManager.getConnection(url, user, password); DatabaseMetaData dbmd = con.getMetaData(); ResultSet rs = dbmd.getColumns(null, schem, "%", "%"); HashMap map = new HashMap(); while (rs.next()) { //printResultSet(rs); String tableName = rs.getString("TABLE_NAME"); String columnName = rs.getString("COLUMN_NAME"); String typeName = rs.getString("TYPE_NAME"); TableVO table = (TableVO) map.get(tableName); if (table == null) { table = new TableVO(); table.setName(tableName); loadPrimaryKeyList( dbmd, table.getName(), table.getPrimaryKeys(), schem); map.put(tableName, table); } table.getColumns().add(columnName); } rs.close(); con.close(); ArrayList list = new ArrayList(); Collection c = map.values(); for (Iterator iter = c.iterator(); iter.hasNext();) { TableVO e = (TableVO) iter.next(); list.add(e); } Collections.sort(list); return list; } /** * dbmdからschemスキーマのtableNameテーブルの主キー情報を取得して * listに格納して返す。 * @param dbmd DB定義情報 * @param tableName テーブル名 * @param list 主キー情報を格納するリスト * @param schem スキーマ名 * @throws SQLException DB例外 */ private static void loadPrimaryKeyList( DatabaseMetaData dbmd, String tableName, ArrayList list, String schem) throws SQLException { //ユニークインデックスで主キーを定義している場合は↓のコードを実行 ResultSet rs = dbmd.getIndexInfo(null, schem, tableName, true, true); //プライマリーキーで主キーを定義している場合は↓のコードのコメントを外す //ResultSet rs = dbmd.getPrimaryKeys(null, schem, tableName); while (rs.next()) { String s = rs.getString("COLUMN_NAME"); if (s != null) { list.add(s); } } rs.close(); } /** * ResultSetを標準出力する * @param rs 標準出力するResultSet * @throws SQLException DBエラー */ private static void printResultSet(ResultSet rs) throws SQLException { while (rs.next()) { ResultSetMetaData rm = rs.getMetaData(); for (int i = 1; i <= rm.getColumnCount(); i++) { System.out.println( i + ":" + rm.getColumnName(i) + ":" + rs.getString(i)); } } } } package tool.db; import java.util.ArrayList; import org.apache.commons.lang.builder.ToStringBuilder; /** * Table情報を格納する * @author yamarou */ public class TableVO implements Comparable { /** テーブル名 */ private String name; /** 列名リスト */ private ArrayList columns = new ArrayList(); /** 主キー名リスト */ private ArrayList primaryKeys = new ArrayList(); /** * オブジェクトの文字列表現を返します。 */ public String toString() { return ToStringBuilder.reflectionToString(this); } /** * 列名リストを返す * @return 列名リスト */ public ArrayList getColumns() { return columns; } /** * テーブル名を返す * @return テーブル名 */ public String getName() { return name; } /** * 主キー名リストを返す * @return 主キー列名リスト */ public ArrayList getPrimaryKeys() { return primaryKeys; } /** * テーブル名を設定する * @param string テーブル名 */ public void setName(String string) { name = string; } /** * オブジェクトを比較する。 */ public int compareTo(Object o) { TableVO table = (TableVO) o; return this.name.compareTo(table.getName()); } }
/* ■実行 java tool.db.SQLGeneretor ■実行結果 c:/TEMP/sql.txtにテキストファイルが出来上がります。 [sql.txt] SELECT ~ INSERT ~ DELETE ~ UPDATE ~   ・   ・   ・ 続く この仕組みを使えばORマッピングクラスや、 JUnitのテストコード等、DB関連のコードを 自動生成したりといったことが出来ると思います。 なかなか使えそうですね♪ ■発行者メールアドレス(ご意見、ご感想、ご要望、ご質問等) yamarou@mail.goo.ne.jp ■発行者webサイト(バックナンバー一気に読めます、リンクで跳べます) http://yamarou.at.infoseek.co.jp/ ■バックナンバー・登録・解除・メールアドレスの変更 http://www.mag2.com/m/0000103290.htm

2009년 9월 24일 목요일

EL식 언어 활용

Java開発者にとって、式言語として最も身近なのは、JSPのELでしょう。

${aaa}

みたいにして、JSPの中に埋め込んでいる式のことです。上記の場合、aaa変数になります。このELをプログラムの中から自由に呼び出せるといろんなことができるようになりますよね。


commons-elを使うとELを簡単に呼び出せるようになります。

キーとなるクラスは、ELParser。ELParser#ExpressionString(String expression)を呼び出すことにより、文字列コンパイルします。

コンパイルした結果は、${}で囲まれている場合Expression型、そうでないばあいにはStringがそのまま返されます。


Expression重要なのは、Expression#evaluate(VariableResolver, FunctionMapper, Logger)のメソッド。VariableResolverを使って、式の中の変数を解決します。JSPファンクションを解決するのが、FunctionMapperです。JSPファンクションといっても実態は、public staticな任意のメソッドを呼び出すことができます。


http://svn.slim3.org/browse/trunk/slim3/slim3-commons/src/main/java/org/slim3/commons/el/Slim3のEL実装があります。Mavenをお使いの方は、slim3-commonsのpom.xmlが参考になるでしょう。

それでは、S3VariableResolverを使ってみましょう。S3VariableResolverのコンストラクタ引数は、変数名と値を関連付けるMapです。

ELParser parser = new ELParser(new StringReader("${aaa}"));
Object exp = parser.ExpressionString();
Map<String, Object> map = new HashMap<String, Object>();
map.put("aaa", "111");
System.out.println(((Expression) exp).evaluate(new S3VariableResolver(map), null, null);

の結果は、111と表示されます。


FunctionMapperの使い方はこんな感じ。

public static int add(int arg1, int arg2) {
    return arg1 + arg2;
}

public void testEvaluateFunction() throws Exception {
    S3FunctionMapper functionMapper = new S3FunctionMapper();
    Method function = getClass().getDeclaredMethod("add", int.class, int.class);
    functionMapper.addFunction("f", "add", function);
    ELParser parser = new ELParser(new StringReader("${f:add(1,2)}"));
    Expression exp = (Expression) parser.EvaluateString();
    assertEquals(3, exp.evaluate(null, functionMapper, null));
}

S3FunctionMapper#addFunction()の最初の引数はprefix、二番目の引数はlocalNameです。ここで登録したメソッドを${prefix:localName(...)}のような感じで呼び出します。


ねっ、簡単でしょ。

2009년 9월 20일 일요일

ZK

ZK http://www.zkoss.org/product/zk.dsp

ZK is the most proven Ajax + Mobile framework available, designed to maximize an enterprise’s operational efficiency and minimize development time and cost


With groundbreaking Direct RIA architecture, ZK simplifies and hastens the creation, deployment and maintenance of rich Internet applications


With direct UI implementation, developing web applications is as straightforward and intuitive as programming desktop applications. By directly communicating with database and enterprise resources, developers have no need to worry about exposure of client side business logic and business data in transit



The benefits of using ZK to enrich enterprise web applications are numerous:

 Rich user experience: Leverage off-the-shelf Ajax components and versatile RIA features to create a responsive and engaging user experience maximizing user satisfaction and work efficiency

  • Over 200 off-the-shelf state-of-art XUL/HTML-complaint Ajax components
  • Numerous third party widgets: JFreeChart, JasperReports, Google Maps, FCKeditor, Timeline, Timeplot, ExtJS, Dojo etc.
  • CSS-based skinning, template-based looks and customizable behavior
  • Drag-and-drop, animation, context menus, and so on
  • Bookmark management and SEO (Search Engine Optimization) supported

 Direct RIA: ZK boosts developer’s productivity by allowing direct implementation and manipulation of user interfaces, databases and enterprise resources.

  • With direct programming, developing Web applications is as straightforward and intuitive as programming desktop applications
  • Displaying data client side is accomplished automatically by transparent and on-demand synchronization between client and server

 Open Source: ZK is the leading open source Ajax + Mobile framework. The ZK developer community is extremely active with over 20 translations, 100 articles/blogs, 100,000 lines of codes, 1,000,000 downloads from 190+ countries.


 Standards-based: ZK is a standard-compliant solution.

  • With XUL and HTML compliant components, ZK protects enterprise applications from behind-closed-doors and proprietary technologies
  • ZK also complies with JSP, JSF, Portlet and Java EE technologies, including the ability to integrate with existing enterprise environments and Java IDEs

  • Please click here for a complete list of supported platforms.

 Markup and scripting Languages: ZK applications can be built using pure Java, markup and/or scripting languages.

  • With XUL/XHTML, designing rich UIs is as simple as authoring HTML pages
  • With Java, Groovy and various other scripting languages supported, developing applications is as rapid as prototyping
  • With annotations and data-binding, accessing database and backend resources can be accomplished effortlessly without writing Java code
  • With Web Accessibility compliance, enterprise applications can be easily be made accessible to people with disabilities

 Direct Push: ZK provides exceptionally robust and intuitive Direct Push technology enabling spontaneous updates sent by the server to Ajax browsers and mobile devices. With ZK’s Direct Push technology, responsive and dynamic enterprise solutions can be created at minimal cost. The technology is also based on strict standards and therefore supports all kinds of application servers and browsers.


 Extensibility and Customizability: ZK is fully customizable and extensible with a modular plug-and-play architecture.

  • With CSS, templates and macro components, the look and behavior of components can be changed dramatically without modifying the application
  • With a pluggable UI factory, each user can have a custom UI loaded from a database or other resource
  • With pluggable variable resolvers and data binding, access to enterprise resources can be achieved automatically
  • With a pluggable performance monitor, the performance of a ZK application can be measured easily; not only the processing time but the communication time aswell

 Security: ZK is designed from the ground up to be secure. ZK protects enterprise applications from cross-site scripting, malicious JavaScript/SQL injection, exposure of client-side business logic, and exposure of business data in transit.

 Scalability, Clustering and Failover: ZK supports high scalability and availability with serializable user interfaces and a pluggable failover manager. ZK is also compatible with the clustering and load balancing support found in modern application servers.


 Mobile Access: ZK extends the reach of enterprise Internet applications to 1 billion mobile devices with minimal cost. ZK supports Java Mobile, Android, and various mobile browsers.


 Enterprise Support: ZK technical support is designed to save development time and enable enterprises to achieve the highest level of user experience, productivity, and performance. Some of our supported customers include Sun Microsystems, Swiss Re, Unisys and MMC, just to name a select few.

ZK spreadsheet

http://www.zkoss.org/product/zkspreadsheet.dsp

ZK Spreadsheet

~ The 1st embeddable Ajax spreadsheet for Java Web application!


ZK Spreadsheet enables Ajax applications to deliver the rich functionality of Excel® within browsers using pure Java. With embeddable Excel® functionality, developers are able to create collaborative and dynamic enterprise applications at minimal cost.



Collaboration
  • Data/Workspace sharing
  • Permission controls
  • Business Intelligence
  • Import and Export Excel files
Ajax
  • Internet access
  • Excel look and feel
  • Zero installation, no ActiveX controls needed, Excel doesn't need to be installed locally
  • Compatible with IE6, IE7, Firefox, Safari, Opera,…
Component
  • Embed ZK Spreadsheet in enterprise applications using pure Java
  • Seamless integration with databases, Web services and other enterprise resources
  • Collaboration with versatile components
Super Grid
  • Large scale data sets
  • Live Data
  • Sorting, filtering, formulating and what-if analysis
  • Excel reporting functionality
Excel Functionalities
  • Over 225 Excel formula functions
  • Fabulous styling
  • Embed images and widgets
  • Selecting, highlighting and merging-cells
  • Freeze rows and columns, lock cells

[Java] include 집중해부

★ JSP에서의 include
http://aboutjsp.com/lec/include.jsp

Last Modified 2003/06/06
Written by hsboy
ReadCount 5287


JSP 에서는 두가지 방법으로 다른 문서를 현재의 문서에 포함 시킬수 있습니다. 이번 강좌에서는 이러한 두가지 include 문에 대해서 알아 봅니다.

* include 란?

다른 웹 언어(PHP or ASP등)를 프로그래밍 해본 경험이 있으신 분들은 include 가 무었인지 잘 알고 있을 것입니다.
include 란 현재의 문서에 다른 문서, 즉 다른 파일의 내용을 포함시켜 출력하는 것을 말합니다. 예를 들어 doc1.jsp 라는 문서의 내용이 아래와 같다고 합시다.

doc1.jsp
<%@ page contentType="text/html;charset=UTF-8"%>
<%
    out.print("<h2>이것은 doc1.jsp의 내용입니다.</h2>");
%>

그리고 doc2.jsp 의 내용이 아래와 같을때

doc2.jsp
<%
    out.print("<h2>이것은 doc2.jsp의 내용입니다.</h2>"); 
%>

위의 두개 문서의 출력을 한번에 보고자 할 때 include를 사용합니다.

doc3.jsp
<%@ page contentType="text/html;charset=UTF-8"%>

<jsp:include page="doc1.jsp" flush="true" />

<%@include file="doc2.jsp" %>

위의 doc3.jsp 를 출력하면 아래와 같은 화면이 출력됩니다.

doc3.jsp 실행화면


위의 소스에서 눈여겨 볼 부분이 doc2.jsp 의 상단 부분인데, doc2.jsp에는 page Directive가 생략 되어 있습니다. 이것은 두가지 include 방식의 차이 때문인데, 자세한 설명은 아래에서 하도록 하겠습니다.
또한 이러한 기능을 SSI(Server Side Include)를 이용해서 구현할수도 있는데 이것은 apache웹서버에서 지원하는 내용 이므로 여기에서는 다루지 않도록 하겠습니다. 자세한 내용이 궁금하신분은 여기를 참고 하시기 바랍니다.


* JSP Action - <jsp:include page="URI" flush="true" />

[syntax]
1). body 구문이 없는 경우
<jsp:include page="URI" flush="true" />

2). body 구문이 있는 경우
<jsp:include page="URI" flush="true">
<jsp:param name="파라메터이름" value="파라메터값" /> /* xxx.jsp?파라메터이름=파라메터값 */
</jsp:include>  

위와 같이 두가지 사용 용법이 있으며, 두번째 방법을 사용하면 해당 jsp파일에 파라메터값도 넘겨 줄수가 있습니다.
JSP Action 구문의 include 는 include되는 파일과 include 시키는 파일(doc1.jsp와 doc3.jsp)를 각각 컴파일 한후 두 파일의 실행 결과를 한곳에 합쳐서 출력을 하게 됩니다. 즉, 완전히 "별도로" 동작하게 됩니다.
여기에서 flush="true" 문장은 true나 false 가 들어 갈수 있는 부분으로써 include를 실행하기 전에 out.flush()를 실행할지 여부를 결정하는 것입니다. 물론 true일때 out.flush()를 실행하겠지요. JSP 스펙 1.1 까지는 반드시 true로 설정이 되어 있어야만 했으니, 1.2 부터는 true/false중 원하는것을 선택하면 됩니다.


* include 지시어 - <%@ include file="URI" %>

include 지시어 와 Action 구문과의 가장 큰 차이점은 include 지시어는 컴파일 되기전에 파일이 내용이 합쳐진다는 것입니다. 즉, doc3.jsp 는 doc2.jsp의 내용을 자신의 문서내에 포함하여 하나의 파일로 인식한다는 것입니다. doc2.jsp 에 보면 page Directive 가 생략이 되어 있는데, 그것이 바로 이러한 이유 때문입니다.

doc2.jsp에도 page Directive를 설정해 주었다면 에러가 발생할 것입니다. 하나의 페이지에 두번 선언을 하는 꼴이 되어 버릴테니까 말이죠.


* Action 구문과 include 지시어의 중요한 차이점

JSP프로그래밍을 조금이라도 접해 보신 분들이라면 누구나 아는 대로 JSP는 먼저 servlet 으로 변환되고, 그 다음 servlet 이 컴파일 되어 그결과를 화면에 출력해 주게 되어 있습니다.
그런데, Action 구문을 사용 하였을 때에는 두개의 파일 각각 다른 파일처리 되어 두개의 servlet 파일 생성하게 됩니다. 따라서 어느 한 파일이 수정되면 곧바로 적용되어 화면에 출력이 되게 됩니다.

하지만 include 지시어 문을 사용하게 되면 하나의 servlet 파일이 생성되게 됩니다. 이로 인해 엄청난 차이점이 발생하게 되는데, JSP의 특성상 JSP파일이 조금이라도 수정이 되어 있으면 servlet 으로 재 변경되어 다시 컴파일이 이루어 지게 됩니다. 그런데, doc2.jsp 파일을 내용을 수정하고, doc3.jsp 파일을 부르게 되면 수정되기 전의 doc2.jsp 파일의 내용이 출력됩니다.

또다시 doc3.jsp 파일을 살짝 고치고 doc3.jsp 을 부르게 되면 이제서야 수정된 doc2.jsp파일의 내용이 화면에 출력 되게 될 것입니다. 눈치 빠르신 분들은 알아 차리셨으리라 생각됩니다만..
이렇게 된 원인은 아무리 doc2.jsp의 내용이 수정된다 하더라도 JSP엔진에서는 doc3.jsp가 수정이 되지 않아 JSP 엔진에서는 수정되지 않은 같은 파일로 인식하여, servlet 파일을 다시 생성하지 않았기 때문입니다.

따라서, include 지시어 문을 사용하셨을 경우에는 두개의 파일 모두 수정해 주어야(doc3.jsp는 공백하나가 추가 되더라도 수정되어야 합니다) 원하는 결과를 얻을수가 있게 됩니다.
이경우 하나의 파일을 여러개의 파일에서 include 지시어 로 include 하였다면 이것은 치명적일수도 있습니다. 예를 들어 dbcon 같은 내용을 만들어 include 해서 사용하는 경우 상당히 많은데, 이럴때 큰 문제 거리가 될수도 있습니다.
이러한 문제점을 한번에 해결하는 방법이 있는데, ...tomcat/ 디렉토리에 보면 work 라는 디렉토리가 있습니다. 이곳이 바로 변환된 servlet 파일들이 저장되어 있는 곳인데, 이 디렉토리를 완전 삭제 한후에 tomcat을 재시작 시키면, 변경된 내용들이 한번에 적용이 될것입니다.(모든 servlet 파일이 재작성되니 당연한 결과 이겠지요)
그런데 이러한 특징은 tomcat 5 버젼대부터 달라지게 되었는데, include되는 파일을 수정하더라도 서블릿 컨테이너가 알아서 모두 재 컴파일 해준다는 것입니다. 필자가 확인한 바로는 OC4J 최신 버젼에서도 tomcat 5와 같이 자동으로 처리되었습니다.

2009년 9월 15일 화요일

HiRDB meta info read

★Oracleの場合
【テーブル一覧取得】
SELECT
TB.TABLE_NAME
,CM.COMMENTS
FROM
USER_TABLES TB
INNER JOIN USER_TAB_COMMENTS CM ON
TB.TABLE_NAME = CM.TABLE_NAME
ORDER BY
TB.TABLE_NAME

【カラム一覧取得】
SELECT
CL.COLUMN_NAME
,CM.COMMENTS
FROM
USER_TAB_COLUMNS CL
INNER JOIN USER_COL_COMMENTS CM ON
CL.TABLE_NAME = CM.TABLE_NAME
WHERE
CL.TABLE_NAME = ''
ORDER BY
CL.COLUMN_ID


★HiRDBの場合
【テーブル一覧取得】
SELECT
TABLE_NAME
,TABLE_COMMENT
FROM
MASTER.SQL_TABLES
WHERE
TABLE_SCHEMA = USER
ORDER BY
TABLE_NAME
WITHOUT LOCK NOWAIT

【カラム一覧取得】
SELECT
COLUMN_NAME
,COLUMN_COMMENT
FROM
MASTER.SQL_COLUMNS
WHERE
TABLE_SCHEMA = USER
AND TABLE_NAME = ''
ORDER BY
COLUMN_ID
WITHOUT LOCK NOWAIT

2009년 9월 14일 월요일

[freemarker] readme.ftl テンプレートを使って [Template]

readme.ftl テンプレートを使って [Template]

Alfrescoには、スペースにreadme.htmlをいれておくと、
その内容をカスタム表示してくれるテンプレートが用意されています。


(1)readme.ftlの内容

<#-- Displays the contents of readme.html and/or the evaluated readme.ftl
                 if they exist in the current space. -->
 
<#assign htmlFilename = "readme.html"/>
<#assign ftlFilename = "readme.ftl"/>
 
<#if space?exists>
    <#if space.childByNamePath["${htmlFilename}"]?exists>
        ${space.childByNamePath[htmlFilename].content}
    </#if>
    <#if space.childByNamePath["${ftlFilename}"]?exists>
        <#include space.childByNamePath["${ftlFilename}"].nodeRef>
    </#if>
</#if>

(2)readme.html

<html>
<head>
<title>readme</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<h4>**User&Group**</h4>
<table border="1">
 <tr>
  <td>No.</td>
  <td>機能</td>

  <td>呼出html</td>
  <td>Javascript</td>
  <td>データファイル名</td>
  <td>log 又は list ファイル名</td>
 </tr>
 <tr>
  <td>1</td>

  <td>ユーザー作成</td>
  <td>create_user.html</td>
  <td>create_user.js</td>
  <td>user_data.csv</td>
  <td>create_user_log.txt</td>
 </tr>

 <tr>
  <td>2</td>
  <td>グループ作成</td>
  <td>create_group.html</td>
  <td>create_group.js</td>
  <td>group_UTF-8.csv</td>

  <td>create_group_log.txt</td>
 </tr>
 <tr>
  <td>3</td>
  <td>ユーザーをグループに登録</td>
  <td>addperson.html</td>
  <td>addperson.js</td>

  <td>user_data.csv</td>
  <td>addperson_log.txt</td>
 </tr>
 <tr>
  <td>4</td>
  <td>フォルダにグループとパーミッションをセット</td>
  <td>permission_set.html</td>

  <td>permission_set.js</td>
  <td>permission_data.csv</td>
  <td>permission_set_log.txt</td>
 </tr>
 <tr>
  <td>5</td>
  <td>フォルダのリストを取る</td>

  <td>folder_list.html</td>
  <td>folder_list.js</td>
  <td>&nbsp;</td>
  <td>folder_list.txt</td>
 </tr>
 <tr>
  <td>6</td>

  <td>グループと属するメンバーのリストを作成</td>
  <td>group_list.html</td>
  <td>group_list.js</td>
  <td>&nbsp;</td>
  <td>group_member_list.txt</td>
 </tr>
</table>
 <br>*注意*<br>

  &nbsp;&nbsp;&nbsp;&nbsp;1.データファイルはdataFolderに、
   scriptはprogramFolderにある。結果はloglistFolderにできる<br>
  &nbsp;&nbsp;&nbsp;&nbsp;2.実際に使用するときは、
   現在テスト用にしてあるフォルダ名などを変更する必要有り<br>
 </body>
</html>


(3)スペースにreadme.htmlをアップロードして、カスタム表示に
  readme.ftlテンプレートを適用すると、

readme.png

  となります。

(注)画面に表示されているJavascriptなどはテスト用に実際に作成したものです。
  呼び出しhtmlはアンカーをつければ、この画面から開くこともできます。


 nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:資格・学び

コンテナ数・ドキュメント数を表示するテンプレート [Template]

スペースのコンテナ数(サブフォルダ数)とドキュメント数を表示する
テンプレートを作成しました。

(あるスペースの下の階層の全サブフォルダ・全ドキュメントの名前と数を調べる
      必要に迫られてJavascriptを作った時に使用したものの一部です)

(1)count02.ftl を作成
 Company Home>Data Dictionary> Presentation Templates スペースにアップロード

<b>${space.name} children count: ${space.children?size}</b><br>
<#assign countC = 0>
<#assign countD = 0>
<#assign countR = 0>
   <#list space.children as child>
      <#if child.isContainer>
             <#assign countC = countC + 1>
   <#elseif child.isDocument>
             <#assign countD = countD + 1>
      <#else>      
             <#assign countR = countR + 1>
             <#assign othername = child.name>
      </#if>
   </#list>
 ${space.name} children Container count: ${countC}<br>
 ${space.name} children Document count: ${countD}<br>
 ${space.name} children ruleFolder count: ${countR}<br>

 

(2)MyHomeのカスタム表示に、そのテンプレートを適用する

countftl04.png

countftl01.png

(注)このテンプレートでは、スペース直下のフォルダ数ドキュメント数しか表示されません。


 nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:資格・学び

バージョン履歴 [Template]

Alfrescoではコンテンツのバージョン管理ができる

(バージョンのつけ方の説明は後日にゆずる
 前回テンプレートのことを書いたので、バージョンの履歴をテンプレートで表示してみる)

(1) version を表示するテンプレートをつくり
        Company Home > Data Dictionary > Presentation Templates スペースにアップロードする

  http://wiki.alfresco.com/wiki/FreeMarker_Template_Cookbook を参考にしてテンプレート作成

(2) webclient から見ると

version02.gif


**** とても便利な機能です。


メールのテンプレートを日本語化 [Template]

2009/05/20 メールのテンプレートを日本語化

(1)Alfrescoではwebclientのアクション・JavaScript・workflowなどいろいろな場面から
  メールを出すことができる。
    Company Home > Data Dictionary > Email Templates スペースに
    そのためのメールテンプレートが用意されている。

  今回はそれを日本語化したものを作ってみた。
  それを上記スペースにアップロードしておけば、利用時に選択できる。

mail_ftl.jpg

(2) invite_user_email.ftl ---->  invite_user_emai_ja.ftl

**テンプレートの内容**

あなたは、スペース '${space.name}' に招待されました。
招待したのは '${person.properties.firstName}<#if person.properties.lastName?exists>

${person.properties.lastName}</#if>'.

権限は the role of: ${role} です。

スペースへのリンク:
<#assign ref=space.nodeRef>
<#assign workspace=ref[0..ref?index_of("://")-1]>
<#assign storenode=ref[ref?index_of("://")+3..]>
http://yourserver:8080/alfresco/navigate/browse/${workspace}/${storenode}

お知らせでした。

Alfresco


(3) notify_user_email.ftl ----->  notify_user_email_ja.ftl

**テンプレートの内容**

新しい投稿 '${document.name}'が、スペース'${space.name}' に届きました。
届けたのは '${person.properties.firstName}<#if person.properties.lastName?exists>

${person.properties.lastName}</#if>'.

ドキュメントへのリンク:
http://yourserver:8080/alfresco${document.url}

スペースへのリンク:
<#assign ref=space.nodeRef>
<#assign workspace=ref[0..ref?index_of("://")-1]>
<#assign storenode=ref[ref?index_of("://")+3..]>
http://yourserver:8080/alfresco/navigate/browse/${workspace}/${storenode}

お知らせでした。

Alfresco

(3) 利用例

mail_ftl_rei01.jpg

mail_ftl_rei02.jpg

(4) Alfresco では テンプレートとして freemarker がよく使用される
  参考URL       http://freemarker.org/
   マニュアルのURL  http://freemarker.org/docs/index.html

  (注意) ftl ファイルはテキストファイルだが、UTF-8で保存するこ

2009년 9월 12일 토요일

Java-FreeMarkerのサンプル

http://park.geocities.jp/gdfsm000/java/java24.html

Java-FreeMarkerのサンプル
FreeMarkerの一番最初のサンプルです。
netbeans6.1でテストしてみましたが、test.ftlはutf-8で保存されるのですが、
それだと実行したときにtest.ftlに書いた日本語(朝、昼、夜)が文字化けします。
別のエディタで、shift_jisに変更して保存するとすべて正常に表示されます。

配列を使用した例

test.ftl

<html>
<head>
  <title>FreeMarker Example Web Application 1</title>
  <meta http-equiv="Content-type" content="text/html; charset=shift_JIS">
</head>
<body>
  ${message}
<br><br>
<table>
<tr><td>朝</td><td>昼</td><td>夜</td></tr>
<#list ar as val>
<tr>
    <#list val as v>
        <td>${v}</td>
    </#list><br>
</tr>
</#list>
</body>
</html>

HelloServlet.java

package example;

import java.util.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import freemarker.template.*;
import java.lang.reflect.Array;

public class HelloServlet extends HttpServlet {
    private Configuration cfg; 
    
    public void init() {
        cfg = new Configuration();
        cfg.setServletContextForTemplateLoading(
                getServletContext(), "WEB-INF/classes/templates");
    }
    
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
        
        // Build the data-model
        Map root = new HashMap();
        root.put("message", "おはようございます");
        String[] ar = {"おはようございます","こんにちは","こんばんは"};
        String[] br = {"goog morning","good arternoon","Goodevening"};
        ArrayList cr = new ArrayList();
        cr.add(ar);
        cr.add(br);
        root.put("ar", cr);
        Template t = cfg.getTemplate("test.ftl");

        resp.setContentType("text/html; charset=" + t.getEncoding());
        Writer out = resp.getWriter();

        try {
            t.process(root, out);
        } catch (TemplateException e) {
            throw new ServletException(
                    "Error while processing FreeMarker template", e);
        }
    }
}

MAPを使用した例

test2.ftl

<html>
<head>
  <title>FreeMarker Example Web Application 1</title>
<meta http-equiv="Content-Type" content="text/html; charset=MS932">
</head>
<body>
  ${message}
<hr>
<table border=1>
  <tr><th>朝</th><th>昼</th><th>夜</th>
  <#list ar as value>
      <tr><td>${value.a}<td>${value.b}<td>${value.c!"<br>"}</tr>
  </#list>
</table>
<br><br>
これはテストの表示です
</body>
</html>

HelloServlet2.java

package example;

import java.util.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import freemarker.template.*;

public class HelloServlet2 extends HttpServlet {
    private Configuration cfg; 
    
    public void init() {
        cfg = new Configuration();
        cfg.setServletContextForTemplateLoading(
                getServletContext(), "WEB-INF/classes/templates");
    }
    
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
        Map root = new HashMap();
        root.put("message", "Hello World!");
        HashMap ar = new HashMap();
        HashMap br = new HashMap();
        ar.put("a", "おはようございます");
        ar.put("b", "こんにちは");
        ar.put("c", "こんばんは");
        br.put("a", "Good Morning");
        br.put("b", "Good Afternoon");
        Object[] cr = {ar, br};
        root.put("ar", cr);
        Template t = cfg.getTemplate("test2.ftl");
        resp.setContentType("text/html; charset=" + t.getEncoding());
        Writer out = resp.getWriter();
        try {
            t.process(root, out);
        } catch (TemplateException e) {
            throw new ServletException(
                    "Error while processing FreeMarker template", e);
        }
    }
}

SAP(ABAP) 관련 좋은 사이트

SAP(ABAP) 관련 좋은 사이트 Sap

2008/11/07 01:33

복사 http://blog.naver.com/tyboss/70036990289

<이 자료는 2006 Vision님의 블로그에서 퍼 온 글입니다. >


http://cma.zdnet.com/book/abap/ch03/ch03.htm

http://help.sap.com/saphelp_40b/helpdata/en/4f/991f82446d11d189700000e8322d00/applet.htm SAP Online Help For Dictionary.


http://sappoint.com/abap/ for SAPscripts

For follg., refer http://www.henrikfrank.dk/abapuk.html
Please note that I do not offer any support for the examples !

ABAP objects and control technology
IDOC
SapScript
Performance tuning
BAPI Programming
Visual Basic Integration - Using the DCOM Connector and BAPI OCX (Only available in Danish)
JAVA and the SAP java connector

 

http://www.sts.tu-harburg.de/teaching/sap_r3/ABAP4/abapindx.htm
for keywords

very useful link for all
http://www.sapgenie.com/abap/index.htm
http://www.sap-img.com/abap.htm
http://www.sapdevelopment.co.uk/tips/tipshome.htm
http://help.sap.com/printdocu/core/Print46c/en/Data/Index_en.htm
http://sap.ittoolbox.com/nav/t.asp?t=322&p=322&h1=322
http://sap.ittoolbox.com/nav/t.asp?t=448&p=448&h1=448
http://www.thespot4sap.com/
http://www.kabai.com/abaps/q.htm
http://www.geocities.com/mpioud/Abap_programs.html
http://www.sapgenie.com/abap/tips_and_tricks.htm
http://www.sapassist.com/code/d.asp?whichpage=1&pagesize=10&i=10&a=c&o=&t=&q=&qt=

For FAQ
http://www.sap-img.com/abap/more-than-100-abap-interview-faqs.htm
http://www.sapgenie.com/faq/abap.htm

BAPI-step by step
http://www.sapgenie.com/abap/bapi/example.htm
http://www.sapgenie.com/abap/bapi/example.htm
Weblog for receive email and processing it through ABAP
https://www.sdn.sap.com/sdn/weblogs.sdn?blog=/pub/wlg/795


For Logical database
http://help.sap.com/saphelp_46c/helpdata/en/9f/db9bed35c111d1829f0000e829fbfe/frameset.htm

very useful
http://help.sap.com/saphelp_46c/helpdata/EN/35/2cd77bd7705394e10000009b387c12/frameset.htm


Useful link to websites

http://www.hernangn.com.ar/sap.htm

Useful for background
http://www.sappoint.com/basis/bckprsng.pdf
http://help.sap.com/saphelp_nw04/helpdata/en/6f/08703713bf277ee10000009b38f8cf/frameset.htm
http://publib.boulder.ibm.com/infocenter/wbihelp/index.jsp?topic=/com.ibm.wbix_adapters.doc/doc/mysap4/sap4x41.htm

Table control in BDC
http://www.sap-img.com/abap/bdc-example-using-table-control-in-bdc.htm

For posting weblog,
https://www.sdn.sap.com/sdn/weblogs.sdn?blog=/pub/wlg/1936

Dynamic Internal table -weblog in sdn
https://www.sdn.sap.com/sdn/weblogs.sdn?blog=/pub/wlg/1011

Smartforms
http://www.sap-basis-abap.com/sapsf001.htm
http://www.sap-press.com/downloads/h955_preview.pdf
http://www.ossincorp.com/Black_Box/Black_Box_2.htm
http://www.sap-img.com/smartforms/sap-smart-forms.htm
http://www.sap-img.com/smartforms/smartform-tutorial.htm
http://www.sapgenie.com/abap/smartforms.htm


How to trace smartform
http://help.sap.com/saphelp_47x200/helpdata/en/49/c3d8a4a05b11d5b6ef006094192fe3/frameset.htm

For step-by-step explanations,check here.
https://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.km.cm.docs/library/uuid/ccab6730-0501-0010-ee84-de050a6cc287
https://sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.km.cm.docs/library/uuid/8fd773b3-0301-0010-eabe-82149bcc292e
https://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.km.cm.docs/library/uuid/3c5d9ae3-0501-0010-0090-bdfb2d458985

Workflow
http://www.sap-img.com/workflow/sap-workflow.htm
http://help.sap.com/saphelp_47x200/helpdata/en/a5/172437130e0d09e10000009b38f839/frameset.htm
For examples on WorkFlow...check the below link..
http://help.sap.com/saphelp_47x200/helpdata/en/3d/6a9b3c874da309e10000000a114027/frameset.htm
http://help.sap.com/printdocu/core/Print46c/en/data/pdf/PSWFL/PSWFL.pdf
http://help.sap.com/saphelp_47x200/helpdata/en/4a/dac507002f11d295340000e82dec10/frameset.htm
http://www.workflowing.com/id18.htm
http://www.e-workflow.org/
http://web.mit.edu/sapr3/dev/newdevstand.html


ALV
http://www.geocities.com/mpioud/Abap_programs.html
Conversion ALV to E-mail,PDF
http://www.sapdevelopment.co.uk/reporting/rep_spooltopdf.htm

Mail
http://www.geocities.com/mpioud/Z_EMAIL_ABAP_REPORT.html
http://www.thespot4sap.com/Articles/SAP_Mail_SO_Object_Send.asp
http://www.sapdevelopment.co.uk/reporting/email/attach_xls.htm
Rich Heilman has provided sample code for sending mail in html-format:
https://www.sdn.sap.com/irj/sdn/thread?forumID=50&threadID=64062&messageID=679478

Sending mail in background or spool mail
http://www.sap-basis-abap.com/sapac018.htm

BOM Explosion
https://www.sdn.sap.com/sdn/weblogs.sdn?blog=/pub/wlg/1647

BOM
http://help.sap.com/saphelp_erp2005/helpdata/en/ea/e9b7234c7211d189520000e829fbbd/frameset.htm
http://help.sap.com/saphelp_erp2005/helpdata/en/d1/2e4114a61711d2b423006094b9d648/frameset.htm
http://www.sap-img.com/sap-sd/sales-bom-implementation.htm
http://www.sap-basis-abap.com/sappp007.htm

OLE
http://www.sapgenie.com/abap/ole.htm
http://help.sap.com/saphelp_46c/helpdata/en/59/ae3f2e488f11d189490000e829fbbd/frameset.htm

ALVGRID with refresh
http://www.geocities.com/mpioud/Z_DEMO_ALV_REFRESH_BUTTON.html

For language setting and decimal separator
https://www.sdn.sap.com/sdn/weblogs.sdn?blog=/pub/wlg/1015

Oracle queries
http://sqlzoo.net/
To format SQL
http://www.sqlinform.com/


SCOT settings
http://www.sap-img.com/basis/basis-faq.htm

Status Icon [ALV,Table Control,Tab Strip]
http://www.sapdesignguild.org/resources/MiniSG-old/from_develop/norm_status_icons.htm#positioning_4

ALV Group Heading
http://www.sap-img.com/fu037.htm

For multiMedia
https://www.sdn.sap.com/irj/sdn/weblogs?blog=/pub/wlg/995

Uploading LOGO in SAP
http://www.sap-img.com/ts001.htm


LSMW

http://www.sap-img.com/sap-data-migration.htm
http://www.sapgenie.com/saptech/lsmw.htm
http://sapabap.iespana.es/sapabap/manuales/pdf/lsmw.pdf
http://www.sap.info/public/INT/int/glossary/int/glossaryletter/Word-17643ed1d6d658821_glossary/L#Word-17643ed1d6d658821_glossary

OOPS ALV

OOPS - Events.
Editable ALV
Tree
TabStrip
Multigrid


Check this for basic concepts of OOPS
https://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.km.cm.docs/library/webas/abap/abap%20code%20samples/ABAP%20Objects/ABAP%20Code%20Sample%20to%20Learn%20Basic%20Concept%20of%20Object-Oriented%20Programming.doc
https://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.km.cm.docs/library/webas/abap/abap%20code%20samples/ALV%20grid/ABAP%20Code%20Sample%20to%20Display%20Data%20in%20ALV%20Grid%20Using%20Object%20Oriented%20Programming.doc

Tabstrip
https://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.km.cm.docs/library/webas/abap/abap%20code%20samples/ALV%20grid/ABAP%20Code%20Sample%20for%20Tab%20Strip%20in%20ALV.pdf

Editable ALV
https://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.km.cm.docs/library/webas/abap/abap%20code%20samples/ALV%20grid/ABAP%20Code%20Sample%20to%20Edit%20ALV%20Grid.doc

Tree
http://www.sapdevelopment.co.uk/reporting/alv/alvtree/alvtree_usrint.htm

General Tutorial for OOPS
https://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.km.cm.docs/library/webas/abap/An%20Easy%20Reference%20for%20ALV%20Grid%20Control.pdf

Function Module
http://www.geocities.com/victorav15/sapr3/abapfun.html

Smartforms
https://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.km.cm.docs/library/uuid/ccab6730-0501-0010-ee84-de050a6cc287
https://sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.km.cm.docs/library/uuid/8fd773b3-0301-0010-eabe-82149bcc292e
https://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.km.cm.docs/library/uuid/3c5d9ae3-0501-0010-0090-bdfb2d458985

Table Control
https://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.km.cm.docs/documents/a1-8-4/Table%20Control%20in%20ABAP.pdf

Freemarker사용법 [출처] Freemarker사용법|작성자 sikunix

1. @macro
 - 프리마커 템플릿 전역에서 공통으로 사용되는 UI 디펜던트한 함수는 매크로로 만들어 여러 ftl에서 사용할 수 있도록 해준다. 샘플을 참고하도록 한다.
 - 형식 : <@매크로명 변수1, 변수2, ... />
 - 샘플1) 긴 문자열을 적당한 크기로 자르는 기능의 매크로
   *사용법 : <@trimX ${item.title}, 20 />
   *매크로 :
   <#macro trimX src max><#compress>
        <#if src?length &gt; max>
              ${src[0..max-1]}..
        <#else>
              ${src}
        </#if>
   </#compress></#macro>

 

 

 - 샘플2) YYYYMMDD 형식의 문자열을 YYYY.MM.DD 형식으로 변환하는 매크로
   *사용법 : <@parseDay ${item.regdate} />
   *매크로 :
   <#macro parseDay src><#compress>
         <#if src?length == 8>
               ${src[0..3]}.${src[4..5]?number}.${src[6..7]?number}
         <#else>
               ${src}
         </#if>
   </#compress></#macro>

 

2. #list
 - 배열 형식의 오브젝트를 루핑 처리할때 사용하는 프리마커 지시자이다. “로컬엘리어스_index” 라는 변수는 0부터 시작하는 시퀀스번호이다.
 - 형식 : <#list 배열객체 as 로컬엘리어스명></#list>
 - 샘플1)
   <#list LIST as item>
          번호 : ${item_index+1} | 이름 : ${item.name} | 아이디 : ${item.id}
   </#list>

 

3. #if
 - 프리마커 조건문에 사용되는 지시자이다.
 - 형식 : <#if 조건식></#if>
 - 샘플1) string 비교
   <#if ENTITY.usergrade == “A” >......</#if>
 - 샘플2) number 비교
   <#if ENTITY.userclass?number == 3>.....</#if>
 - 샘플3) boolean 비교
   <#if ENTITY.isAuth()>.....</#if>

 

4. #break
 - Loop문을 중단하고 다음 스크립트로 넘어가려고 할때 사용되는 지시자이다.
 - 형식 : <#break>
 - 샘플1) 루프문을 실행하는 중 5번째에서 escape 하는 예
 <#list LIST as item>
  <#if item_index &gt; 3><#break></#if>
 </#list>

 

5. #assign
 - 프리마커내에서 사용자 정의 로컬변수가 필요할 때 사용하는 지시자이다.
 - 형식 : <#assign 로컬변수명 = 초기화값>
 - 샘플1) <#assign CHECK = item_index>

 

6. [x...y]
 - 문자열의 일정 범위를 자를때 사용하는 함수
 - 형식 : ${문자열[1..5]}
 - 샘플1) ${item.name[1..5]}

 

7. ?has_content
 - 리스트형 오브젝트가 null이 아니고 최소 1개 이상의 컨텐츠를 가지고 있는지 체크하는 함수로써 ?has_content는 ?exists와 ?size>0 두가지 체크를 동시에 해주는 함수이다.
 - 형식 : 리스트오브젝트?has_content
 - 샘플1) <#if LIST?has_content>.....</#if>

 

8. ?exists
 - NULL체크 함수. if_exists는 <#if 지시자 없이도 사용할 수 있게 해주는 표현식이다.
 - 형식 : 오브젝트?exists
 - 샘플1) <#if ENTITY.username?exists>${ENTITY.username?substring(0, 5)}</#if>
 - 샘플2) <#if LIST?exists && LIST?size &gt; 0>.....</#if>
 - 샘플3) ${ENTITY.username?if_exists}

 

9. ?default
 - NULL값을 대체해주는 함수
 - 형식 : 오브젝트?default(디폴트값)
 - 샘플1) ${item.userclass?default(“99”)}
 - 샘플2) ${item.age?default(20)}

 

10. ?string
 - 문자열로 형변환하는 함수
 - 형식 : 오브젝트?string
 - 샘플1) <#if item.age?string == “29”>.....</#if>
 - 샘플2) ${item.regdate?string(“yyyy/MM/dd HH:mm”)}
 - 샘플3) 숫자를 통화표시로 나타내는 예
  <#assign MONEY = 1234567>
  ${MONEY?string(",##0")}

 

11. ?number
 - 숫자로 형변환하는 함수
 - 형식 : 오브젝트?number
 - 샘플1) <#if item.userclass?number &gt; 3>.....</#if>
 - 샘플2) ${LIST_POINTS[item.gid?number].entityname?default(“”)}

 

12. ?js_string
 - 문자열을 자바스크립트에 유효하도록 필터링해주는 함수. 문자열내에 싱글쿼테이션(‘)등이 포함되어 스크립트에 오류가 나는것을 방지하기 위하여 사용되는 함수이다. 화면상에는 HTML 태그로 취급된다.
 - 형식 : 오브젝트?js_string
 - 샘플1) 문자열 <img src=’/image/enterprise.gif’>을 js_string으로 처리했을때 소스보기를 하면 <img src=\’/image/enterprise.gif\’>으로 출력된다.
 - 샘플2) <a href=”javascript:getName(‘${item.homeurl?js_string}’);”>

 

13. ?html
 - 문자열을 HTML Symbolic Entity로 필터링해주는 함수. 문자열내의 HTML태그등을 깨뜨려 화면상으로 출력되도록 할때 사용하는 함수이다. 화면상에 HTML태그가 아닌 일반 문자열로 취급된다.
 - 형식 : 오브젝트?html
 - 샘플1) 문자열 <img src=’/image/enterprise.gif’>을 html로 처리하면 화면상에 <img src=’/image/enterprise.gif’> 로 출력되고 소스보기를 하면 &lt;img src=’/image/enterprise.gif’&gt;로 출력된다.

 

14. ?index_of
 - 특정 문자(열)가 시작되는 위치를 정수형으로 반환한다. 인덱스는 0부터 시작됨.
 - 형식 : 오브젝트?index_of(특정문자)
 - 샘플1) “abcde”?index_of(“c”) 는 2를 반환한다.

 

15. ?replace
 - 문자열의 일부를 주어진 문자로 대체하는 함수
 - 형식 : 오브젝트?replace(찾을문자열, 대체할문자열)
 - 샘플1) ${item.content?replace(“>”, “&gt;”)}

 

16. item_has_next
 -리스트 객체의 다음 컨텐츠가 존재하는지(EOF) 체크하는 함수
 -형식 : 리스트엘리어스이름_has_next
 -샘플1) 이름과 이름사이에 , 를 찍어주되 마지막은 찍지 않는 경우의 예
  <#list LIST as item>
 ${item.name?default(“”)}<#if item_has_next>,</#if>
  </#list>

var dan = 2; var imgOption = 1; var bodyWidth = 826; var resizeYn = "N"; resize_back("Postframe", "W", '1', '826', '1036', '1020'); setTimeout("resize_fr('Postframe', 'W', '1', '826', '1036', '1020')",500); setTimeout("resize_fr('Postframe', 'W')", 500); setTimeout("resize_fr('Postframe', 'W')", 1000); setTimeout("resize_fr('Postframe', 'W')", 2000); setTimeout("resize_fr('Postframe', 'W')", 4000); parent.window.scrollTo(0,0);

[출처] Freemarker사용법|작성자 sikunix

Freemarker에서 사소하지만 사실은 중요한 공백 처리 문제 [출처] Freemarker에서 사소하지만 사실은 중요한 공백 처리 문제|작성자 운용

Freemarker나 각족 템플릿 엔진들을 사용하다 보면, 우리는 직면하게 되는 문제가 하나 있습니다. 바로 공백이나 줄 바꿈 문제입니다. 각종 템플릿 관련 태그들을 쓰다보면 줄도 바꾸게 되고, 이게 어떻게 처리되는가에 따라서 공백이 민감한 파일들에 대해서는 오작동을 유도하기도 하고, 파일 용량 자체를 필요 이상으로 늘리기도 합니다.

 

그렇다면 Freemarker에서는 어떻게 공백을 합리적인 수준으로 제어할 수 있을까요? 이에 대해서 3가지 방법을 우선 생각할 수 있습니다.

  • 방법 1. 줄 단위로 trim을 처리한다.
    • 본 방법은 텍스트 줄 별로 <#t> <#lt> <#rt>을 걸어서 줄 전체에 trim을 걸거나 왼쪽, 오른쪽에 선택적으로 trim을 걸어준다.
  • 방법 2. ftl 태그를 사용해서 freemarker 페이지에  strip_whitespace 세팅을 걸어준다.
    • 템플릿 상단 부에 <#ftl strip_whitespace=true>를 걸어두고 신경을 끄도록 한다.
    • 이 방법이 부하를 줄까 생각을 하지만, 해당 부분에 대해서는 그다지 신경을 많이 쓰지 않아도 된다고 한다.
  • 방법 3. compress 메소를 사용해서 원하는 영역에서 공백을 제거해준다.
    • 원하는 영역을 <#compresss>와 </#compress>로 묶어서 지정된 구간에 대해서 공백을 제거하도록 한다.

위 방법을 적절히 사용해서 공백 처리를 잘 하도록 하자.

경우에 따라서 공백이 문제를 일으키면 오작동 이유를 찾기 어려운 경우가 많다. 각별히 신경써서 조처하도록 하자.

Freemarker에서 상대 경로에서 context root 지정하기 [출처] Freemarker에서 상대 경로에서 context root 지정하기|작성자 sikunix

Freemarker를 다른 웹-어플리케이션 개발에 연동을 하면서 제일 먼저 직면하는 것 중에서 다른 리소스에 대한 링크를 만들고자 할 때 이른바 서비스 컨택스트 루트를 매번 써주어야 하는가 있다. 당연히 그렇지 않다. 그럼 어떻게 해야 하는가!

 

${base}를 사용하면 context root까지 경로가 기입된다.

 

예를 들어서, sample이라는 서비스 컨텍스트를 사용하는 경우에 각종 파일들은 /sample/***.** 형태로 나오게 된다. 그럴 때, 내부 자원에 대해서 링크를 걸어 줄 때는 /sample/을 명시적으로 써주어야 하는 경우들이 있다. 문제는 컨텍스트 이름이 바뀌는 경우이다. 서비스 만들다 보면 그런 경우 빈번하고. 그렇기에 우리는 삽질 하지 않을 방법을 찾아야 한다. 그래서 ${base}를 Freemarker가 제공해 주는 것이다.

 

간단한 팁이지만 알고 있어야 할 팁 중 하나 ${base} ^^

Adobe Flex Builder 3.0.1 Professional 다운로드.

Adobe Flex Builder 3.0.1 Professional 다운로드.

http://www.adobe.com/cfusion/tdrc/index.cfm?product=flex&loc=ko

[FreeMarker] Built-ins for strings

원문 : http://freemarker.sourceforge.net/docs/ref_builtins_string.html

  • substring

FreeMarker 2.3.7 부터 지원

exp?substring(from, toExclusive) 또는 exp?substring(from) 의 형태로 사용

string의 substring. from 은 첫 문자의 인덱스입니다. from 은 0 이상이고, toExclusive 보다 작거나 같아야 합니다. toExclusive 는 부분 문자열의 다음 문자의 인덱스입니다. toExclusive 는 0 이상이고, 문자열 길이보다 작거나 같아야 합니다. toExclusive 를 생략하면 문자열의 길이로 설정됩니다. 정수가 아닌 숫자를 from 이나 toExclusive으로 사용하는 경우 정수 부분만 사용됩니다.



- ${'abc'?substring(0)}
- ${'abc'?substring(1)}
- ${'abc'?substring(2)}
- ${'abc'?substring(3)}

- ${'abc'?substring(0, 0)}
- ${'abc'?substring(0, 1)}
- ${'abc'?substring(0, 2)}
- ${'abc'?substring(0, 3)}

- ${'abc'?substring(0, 1)}
- ${'abc'?substring(1, 2)}
- ${'abc'?substring(2, 3)}

결과

- abc
- bc
- c
-

-
- a
- ab
- abc

- a
- b
- c

  • cap_first

첫 번째 word 의 첫 문자가 대문자인 문자열. word 의 정확한 의미는 word_list built-in 에서 볼 수 있습니다.



${"  green mouse"?cap_first}
${"GreEN mouse"?cap_first}
${"- green mouse"?cap_first}

결과

  Green mouse
GreEN mouse
- green mouse

  • upcap_first

cap_first 의 반대. 첫 word 의 첫 문자가 소문자인 문자열.

  • capitalize

모든 word의 첫 문자가 대문자인 문자열. word 의 정확한 의미는 word_list built-in 에서 볼 수 있습니다.



${"  green  mouse"?capitalize}
${"GreEN mouse"?capitalize}

결과

  Green Mouse
Green Mouse

  • chop_linebreak

끝에 line_break 가 없는 문자열.

  • date, time, datetime

date 값으로 변환된 문자열. 형식에 대한 파라미터를 명시하는 것을 추천합니다.



<#assign test1 = "10/25/1995"?date("MM/dd/yyyy")>
<#assign test2 = "15:05:30"?time("HH:mm:ss")>
<#assign test3 = "1995-10-25 03:05 PM"?datetime("yyyy-MM-dd hh:mm a")>
${test1}
${test2}
${test3}

결과

Oct 25, 1995
3:05:30 PM
Oct 25, 1995 3:05:00 PM

date 가 date_format, time_format, datetime_format 설정에 따라 변환되었다는 것을 유의하십시오. (date 를 string 으로 변환하는 것에 대한 자세한 정보는 string built-in for dates, date interpolations 에서 볼 수 있습니다.) string 을 date 로 변환할 때 사용한 형식은 중요하지 않습니다.

기본 date/time/datetime 형식이 무엇일지 알고 있다면 형식 파라미터를 사용할 필요가 없습니다.

<#assign test1 = "Oct 25, 1995"?date>
<#assign test2 = "3:05:30 PM"?time>
<#assign test3 = "Oct 25, 1995 03:05:00 PM"?datetime>
${test1}
${test2}
${test3}

  • ends_with
문자열이 특정 문자열로 끝나면 true 를 반환합니다. 예를 들어 "redhead"?ends_with("head")는 boolean true 를 반환합니다. "head"?ends_with("head") 역시 true 를 반환합니다.

  • html

html 문자열. 즉, < 는 &lt; 로, > 는 &gt; 로, & 는 &amp; 로, " 는 &quot; 로 치환된 문자열.

안전하게 속성 값을 삽입하고자 한다면, HTML 에서 속성 값을 큰 따옴표로 둘러싸야 한다는 것에 유의하십시오.

<input type=text name=user value="${user?html}">

일반적으로 많은 타이핑을 없애고, escape directive 를 사용함으로써 발생할 수 있는 실수의 가능성을 줄이기 위해, HTML 에서 모든 것에 이  built-in 을 사용하고 싶을 것입니다.

  • groups

matches built-in 의 결과에만 사용됩니다.

  • index_of

특정 문자열이 처음 나타나는 인덱스를 반환합니다. 예를 들어, "abcabc"?index_of("bc") 는 1을 반환합니다. (첫 문자의 인덱스가 0 입을 잊지 마십시오.) 검색을 시작할 인덱스를 지정할 수도 있습니다. "abcabc"?index_of("bc", 2) 는 4를 반환합니다. 두 번째 파라미터의 숫자는 제한이 없습니다. 두 번째 파라미터가 0 보다 작으면, 두 번째 파라미터가 0일 때와 같은 결과를 반환합니다. 두 번째 파라미터가 문자열의 길이보다 크면, 두 번째 파라미터가 문자열의 길이일 때와 같은 결과를 반환합니다. 파라미터가 소수면, 내림한 정수를 사용하여 결과를 반환합니다.

문자열에 첫 번째 파라미터가 존재하지 않으면 -1 을 반환합니다.

  • j_string

Java 언어의 문자열 escaping 규칙에 따라 문자열을 수정합니다. 게다가 Java 언어에 해당하는 escape sequence 가 없는 모든 문자(UCS code point 0x20) 는 UNICODE escape (\uXXXX) 으로 변경됩니다..



<#assign beanName = 'The "foo" bean.'>
String BEAN_NAME = "${beanName?j_string}";

결과

String BEAN_NAME = "The \"foo\" bean.";

  • js_string

JavaScript 언어 문자열 escaping 규칙에 따라 문자열을 변경합니다. 큰 따옴표(") 와 작은 따옴표(') 가 모두 변경됩니다. FreeMarker 2.3.1 부터 > 는 \> 로 치환됩니다. 게다가 JavaScript 에 escape sequence 가 없는 모든 문자 (UCS code point 0x20) 은 16진수 escape (\xXX) 로 치환됩니다. (물론, JavaScript 언어 문자열 syntax 에 따라 백슬래쉬(\) 도 변경되고, line-feed 는 \n 으로 치환됩니다. 등)



<#assign user = "Big Joe's \"right hand\"">
<script>
alert("Welcome ${user?js_string}!");
</script>

결과

<script>
alert("Welcome Big Joe\'s \"right hand\"!");
</script>

  • last_index_of
문자열의 끝에서부터 검색했을 때, 특정 문자열의 인덱스를 반환합니다. 예를 들어, "abcabc"?last_index_of("ab") 는 3을 반환합니다. 검색을 시작할 인덱스를 지정할 수도 있습니다. 예를 들어, "abcabc"?last_index_of("ab", 2) 는 0을 반환합니다. ...
  • length

문자열의 문자 개수
  • lower_case

소문자로 이루어진 문자열

  • left_pad

FreeMarker 2.3.1 부터 지원

파라미터가 1 개면, 문자열의 길이가 파라미터의 값과 같아질 때까지 문자열의 앞에 공백을 삽입합니다. 만약 문자열의 길이와 파라미터와 같거나 파라미터보다 크면 아무 작업도 하지 않습니다.



[${""?left_pad(5)}]
[${"a"?left_pad(5)}]
[${"ab"?left_pad(5)}]
[${"abc"?left_pad(5)}]
[${"abcd"?left_pad(5)}]
[${"abcde"?left_pad(5)}]
[${"abcdef"?left_pad(5)}]
[${"abcdefg"?left_pad(5)}]
[${"abcdefgh"?left_pad(5)}]


결과

[     ]
[ a]
[ ab]
[ abc]
[ abcd]
[abcde]
[abcdef]
[abcdefg]
[abcdefgh]

파라미터가 2 개일 때, 첫 번째 파라미터는 앞에서 언급한 파라미터와 같은 역할을 합니다. 두 번째 파라미터는 문자열의 앞에 삽입할 문자 입니다.



[${""?left_pad(5, "-")}]
[${"a"?left_pad(5, "-")}]
[${"ab"?left_pad(5, "-")}]
[${"abc"?left_pad(5, "-")}]
[${"abcd"?left_pad(5, "-")}]
[${"abcde"?left_pad(5, "-")}]


결과

[-----]
[----a]
[---ab]
[--abc]
[-abcd]
[abcde]

두 번째 파라미터는 문자열이 될 수도 있습니다. 그러면 문자열인 파라미터가 반복하여 삽입됩니다.



[${""?left_pad(8, ".oO")}]
[${"a"?left_pad(8, ".oO")}]
[${"ab"?left_pad(8, ".oO")}]
[${"abc"?left_pad(8, ".oO")}]
[${"abcd"?left_pad(8, ".oO")}]

결과

[.oO.oO.o]
[.oO.oO.a]
[.oO.oOab]
[.oO.oabc]
[.oO.abcd]

두 번째 파라미터는 반드시 길이가 1 이상인 문자열이어야 합니다.

  • right_pad

FreeMarker 2.3.1 부터 지원됩니다.

이 것은 left_pad 와 같지만, 두 번째 파라미터(또는 공백)을 문자열의 앞이 아니라 뒤에 삽입합니다.



[${""?right_pad(5)}]
[${"a"?right_pad(5)}]
[${"ab"?right_pad(5)}]
[${"abc"?right_pad(5)}]
[${"abcd"?right_pad(5)}]
[${"abcde"?right_pad(5)}]
[${"abcdef"?right_pad(5)}]
[${"abcdefg"?right_pad(5)}]
[${"abcdefgh"?right_pad(5)}]

[${""?right_pad(8, ".oO")}]
[${"a"?right_pad(8, ".oO")}]
[${"ab"?right_pad(8, ".oO")}]
[${"abc"?right_pad(8, ".oO")}]
[${"abcd"?right_pad(8, ".oO")}]

결과

[     ]
[a ]
[ab ]
[abc ]
[abcd ]
[abcde]
[abcdef]
[abcdefg]
[abcdefgh]

[.oO.oO.o]
[aoO.oO.o]
[abO.oO.o]
[abc.oO.o]
[abcdoO.o]

  • contains

FreeMarker 2.3.1 부터 지원됩니다.

파라미터가 문자열에 있으면 true 를 리턴합니다.



<#if "piceous"?contains("ice")>It contains "ice"</#if>

결과

It contains "ice"

  • matches

"power user" built-in 입니다. regular expression(정규식) 을 모르면 무시해 주세요.

FreeMarker 2.3.1 부터 지원됩니다.

Java 2 플랫폼 1.4 이상의 버전을 사용할 때만 동작합니다.

이 built-in 은 문자열이 패턴에 해당하는지 판단합니다. 그리고 해당하는 부분 문자열의 리스트를 반환합니다. 반환되는 값은 multi-type 값입니다.

Boolean: 문자열이 패턴과 정확하게 일치하면, true. 아니면, false. 예를 들어, "fooo?matches('fo*') 는 true 지만, "fooo bar"?matches('fo*') 는 false 입니다.



<#if "fxo"?matches("f.?o")>Matches.<#else>Does not match.</#if>

<#assign res = "foo bar fyo"?matches("f.?o")>
<#if res>Matches.<#else>Does not match.</#if>
Matching sub-strings:
<#list res as m>
- ${m}
</#list>


결과

Matches.

Does not match.
Matching sub-strings:
- foo
- fyo

정규식이 groups (괄호) 를 포함하면, groups built-in 으로 접근할 수 있습니다.

<#assign res = "aa/rx; ab/r;"?matches("(\\w[^/]+)/([^;]+);")>
<#list res as m>
- ${m} is ${m?groups[1]} per ${m?groups[2]}
</#list>

결과

- aa/rx; is aa per rx
- ab/r; is ab per r

matches 는 생략 가능한 두 번째 파라미터 flags 를 허용합니다. 항상 정규식을 사용하기 때문에 flag r 은 지원되지 않는다는 것을 유의하십시오.
  • number

숫자로 변환된 문자열. number 는 FTL 에서 직접 숫자를 명시했을 때와 같은 형식이어야 합니다. 즉, 숫자들 사이에 . 이 있는 locale independent form 이어야 한다는말입니다. 추가적으로 이 built-in 은 몇 가지 특정 표현을 인식합니다.(예: "1.23E6", "1.5e-8").

알려진 문제점: Java2 플랫폼 1.3 이전의 버전을 사용하면 이 built-in 은 숫자 앞의 + 와 과학적인 표현을 인식하지 못합니다.

  • replace

문자열의 모든 특정 부분 문자열을 다른 문자열로 치환합니다. 단어를 다루지는 않습니다.



${"this is a car acarus"?replace("car", "bulldozer")}

결과

this is a bulldozer abulldozerus

치환은 왼쪽에서 오른쪽으로 진행됩니다.

${"aaaaa"?replace("aaa", "X")}

결과

Xaa 

첫 번째 파라미터가 길이가 0인 문자열이면, 문자와 문자 사이에 두 번째 파라미터가 삽입됩니다. 예를 들어, "foo"?replace("", "|") 는 "|f|o|o|" 입니다.

replace 는 생략가능한 세 번째 파라미터인 flags parameter 를 허용합니다.

  • rtf

Rich text(RTF text) 인 문자열. 즉, \ 가 \\ 로 치환되고, { 가 \{ 로 치환되고, } 가 \} 로 치환되는 문자열.

  • url

FreeMarker 2.3.1 부터 지원됩니다.

URL escaping 을 거친 문자열. 모든 US-ASCII 가 아닌 문자와 URL 예약어가 %xx 로 치환되는 것을 의미합니다.



<#assign x = 'a/b c'>
${x?url}

결과(US-ASCII compatible charset 을 사용했다고 가정)

a%2Fb%20c

Note that it escapes all reserved URL characters (/, =, &, ...etc), so this encoding can be used for encoding query parameter values, for example:

<a href="foo.cgi?x=${x?url}&y=${y?url}">Click here...</a>  

Note

Above no HTML encoding (?htm) was needed, because URL escaping escapes all reserved HTML characters anyway. But watch: always quote the attribute value, and always with normal quotation mark ("), never with apostrophe quotation mark ('), because apostrophe quotation mark is not escaped by the URL escaping.

To do URL escaping a charset must be chosen that will be used for calculating the escaped parts (%XX). If you are HTML page author and you don't really understand this, don't worry: the programmers should configure FreeMarker so that it uses the proper charset by default (programmers: see more below...). If you are a more technical minded user, then you may want to know that the charset used is specified by the url_escaping_charset setting, that can be set in template execution time (or, preferably, earlier by the programmers). For example:

<#--
This will use the charset specified by the programmers
before the template execution has started.
-->
<a href="foo.cgi?x=${x?url}">foo</a>

<#-- Use UTF-8 charset for URL escaping from now: -->
<#setting url_escaping_charset="UTF-8">

<#-- This will surely use UTF-8 charset -->
<a href="bar.cgi?x=${x?url}">bar</a>

Furthermore, you can explicitly specify a charset for a single URL escaping as the parameter to the built-in:

<a href="foo.cgi?x=${x?url('ISO-8895-2')}">foo</a>  

If the url built-in has no parameter, then it will use the charset specified as the value of the url_escaping_charset setting. This setting should be set by the software that encloses FreeMarker (e.g. a Web application framework), because it is not set (null) by default. If it is not set, then FreeMarker falls back using the value of the output_encoding setting, which is also not set by default, so it is again the task of the enclosing software. If the output_encoding setting is not set either, then the parameterless url built-in can't be executed, and it will cause execution time error. Of course, the url built-in with parameter always works.

It's possible to set url_escaping_charset in the template with the setting directive, but it is bad practice, at least in true MVC applications. The output_encoding setting can't be set with the setting directive, so that's surely the task of the enclosing software. You may find more information regarding this here...


  • split

한 문자열을 여러 문자열로 나눌 때 사용됩니다.



<#list "someMOOtestMOOtext"?split("MOO") as x>
- ${x}
</#list>

결과

- some
- test
- text

모든 분리자가 새로운 아이템 전에 사용된다고 가정하고 있다는 점에 유의하십시오.

<#list "some,,test,text,"?split(",") as x>
- "${x}"
</#list>

결과

- "some"
- ""
- "test"
- "text"
- ""

  • starts_with

특정 문자열로 시작하면 true 를 반환합니다. 예를 들어, "redhead"?starts_with("red") 는 boolean true 를 반환합니다. "red"?starts_with("red") 도 true 를 반환합니다.

  • string(when used with a string value)

아무 일도 하지 않고 현재의 문자열을 반환합니다. 예외는 값이 여러 가지 형태일 때 결과 값이 단순한 문자열이 된다는 것입니다. multi-typing 의 artifact 를 방지하기 위해 활용될 수 있습니다.

  • trim

처음과 끝에 공백이 없는 문자열.



(${"  green mouse  "?trim})

결과

(green mouse)

  • upper_case

대문자로만 이루어진 문자열. 예를 들어, "GrEen MoUsE" 는 "GREEN MOUSE" 가 됩니다.

  • word_list

문자열의 모든 word 의 리스트. word 의 순서는 문자열에 나타나는 순서입니다. word 는 white-space 가 아닌 모든 문자의 연속입니다.



<#assign words = "   a bcd, .   1-2-3"?word_list>
<#list words as word>[${word}]</#list>

결과

[a][bcd,][.][1-2-3]

  • xhtml

XHTML 텍스트인 문자열. 즉, < 는 &lt; 로, < 는 &gt; 로, & 는 &amp; 로, " 는  &quot; 로, ' 는 &#39; 로, ' 는 &apos; 로 치환된 문자열.

이  built-in 과 xml built-in 의 차이는 xhtml built-in 은 ' 을 &apos; 대신 &#39 ;  로 치환하여 사용한다. 왜냐하면 오래된 몇 몇 브라우저는 &apos; 를 바르게 처리하지 못하기 때문이다.
  • xml

XML 텍스트인 문자열. 즉, < 는 &lt; 로, < 는 &gt; 로, & 는 &amp; 로, " 는  &quot; 로, ' 는 &apos; 로, ' 는 &apos; 로 치환된 문자열.
  • Common flags