提交 1e9a21cf authored 作者: Thomas Mueller's avatar Thomas Mueller

XMLTEXT now supports an optional parameter to escape newlines. XMLNODE now…

XMLTEXT now supports an optional parameter to escape newlines. XMLNODE now support an optional parameter to disable indentation.
上级 49d9d2ef
...@@ -3108,9 +3108,12 @@ CALL XMLNODE('a', XMLATTR('href', 'http://h2database.com')) ...@@ -3108,9 +3108,12 @@ CALL XMLNODE('a', XMLATTR('href', 'http://h2database.com'))
" "
"Functions (String)","XMLNODE"," "Functions (String)","XMLNODE","
XMLNODE(elementString [, attributesString [, contentString]]) XMLNODE(elementString [, attributesString [, contentString [, indentBoolean]])
"," ","
Create an XML node element. Create an XML node element.
An empty or null attribute string means no attributes are set.
An empty or null content string means the node is empty.
The content is indented by default if it contains a newline.
This method returns a string. This method returns a string.
"," ","
CALL XMLNODE('a', XMLATTR('href', 'http://h2database.com'), 'H2') CALL XMLNODE('a', XMLATTR('href', 'http://h2database.com'), 'H2')
...@@ -3139,15 +3142,17 @@ CALL XMLCDATA('data') ...@@ -3139,15 +3142,17 @@ CALL XMLCDATA('data')
"Functions (String)","XMLSTARTDOC"," "Functions (String)","XMLSTARTDOC","
XMLSTARTDOC() XMLSTARTDOC()
"," ","
The string ""<?xml version='1.0'?>"" is returned. Returns the XML decrations.
The result is always ""<?xml version=""1.0""?>"".
"," ","
CALL XMLSTARTDOC() CALL XMLSTARTDOC()
" "
"Functions (String)","XMLTEXT"," "Functions (String)","XMLTEXT","
XMLTEXT(valueString) XMLTEXT(valueString [, escapeNewlineBoolean])
"," ","
Creates an XML text element. Creates an XML text element.
If enabled, newlines and linefeeds are converted to XML entities (&#).
This method returns a string. This method returns a string.
"," ","
CALL XMLTEXT('test') CALL XMLTEXT('test')
......
...@@ -254,7 +254,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -254,7 +254,7 @@ public class Function extends Expression implements FunctionCall {
addFunction("XMLCOMMENT", XMLCOMMENT, 1, Value.STRING); addFunction("XMLCOMMENT", XMLCOMMENT, 1, Value.STRING);
addFunction("XMLCDATA", XMLCDATA, 1, Value.STRING); addFunction("XMLCDATA", XMLCDATA, 1, Value.STRING);
addFunction("XMLSTARTDOC", XMLSTARTDOC, 0, Value.STRING); addFunction("XMLSTARTDOC", XMLSTARTDOC, 0, Value.STRING);
addFunction("XMLTEXT", XMLTEXT, 1, Value.STRING); addFunction("XMLTEXT", XMLTEXT, VAR_ARGS, Value.STRING);
addFunction("REGEXP_REPLACE", REGEXP_REPLACE, 3, Value.STRING); addFunction("REGEXP_REPLACE", REGEXP_REPLACE, 3, Value.STRING);
addFunction("RPAD", RPAD, VAR_ARGS, Value.STRING); addFunction("RPAD", RPAD, VAR_ARGS, Value.STRING);
addFunction("LPAD", LPAD, VAR_ARGS, Value.STRING); addFunction("LPAD", LPAD, VAR_ARGS, Value.STRING);
...@@ -634,9 +634,6 @@ public class Function extends Expression implements FunctionCall { ...@@ -634,9 +634,6 @@ public class Function extends Expression implements FunctionCall {
case XMLSTARTDOC: case XMLSTARTDOC:
result = ValueString.get(StringUtils.xmlStartDoc()); result = ValueString.get(StringUtils.xmlStartDoc());
break; break;
case XMLTEXT:
result = ValueString.get(StringUtils.xmlText(v0.getString()));
break;
case DAY_NAME: { case DAY_NAME: {
SimpleDateFormat dayName = new SimpleDateFormat("EEEE", Locale.ENGLISH); SimpleDateFormat dayName = new SimpleDateFormat("EEEE", Locale.ENGLISH);
result = ValueString.get(dayName.format(v0.getDate())); result = ValueString.get(dayName.format(v0.getDate()));
...@@ -1042,7 +1039,8 @@ public class Function extends Expression implements FunctionCall { ...@@ -1042,7 +1039,8 @@ public class Function extends Expression implements FunctionCall {
case XMLNODE: { case XMLNODE: {
String attr = v1 == null ? null : v1 == ValueNull.INSTANCE ? null : v1.getString(); String attr = v1 == null ? null : v1 == ValueNull.INSTANCE ? null : v1.getString();
String content = v2 == null ? null : v2 == ValueNull.INSTANCE ? null : v2.getString(); String content = v2 == null ? null : v2 == ValueNull.INSTANCE ? null : v2.getString();
result = ValueString.get(StringUtils.xmlNode(v0.getString(), attr, content)); boolean indent = v3 == null ? true : v3.getBoolean();
result = ValueString.get(StringUtils.xmlNode(v0.getString(), attr, content, indent));
break; break;
} }
case REGEXP_REPLACE: { case REGEXP_REPLACE: {
...@@ -1207,6 +1205,13 @@ public class Function extends Expression implements FunctionCall { ...@@ -1207,6 +1205,13 @@ public class Function extends Expression implements FunctionCall {
result = v0.convertPrecision(v1.getLong(), v2.getBoolean()); result = v0.convertPrecision(v1.getLong(), v2.getBoolean());
break; break;
} }
case XMLTEXT:
if (v1 == null) {
result = ValueString.get(StringUtils.xmlText(v0.getString()));
} else {
result = ValueString.get(StringUtils.xmlText(v0.getString(), v1.getBoolean()));
}
break;
default: default:
throw DbException.throwInternalError("type=" + info.type); throw DbException.throwInternalError("type=" + info.type);
} }
...@@ -1620,6 +1625,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1620,6 +1625,7 @@ public class Function extends Expression implements FunctionCall {
case TRIM: case TRIM:
case FILE_READ: case FILE_READ:
case ROUND: case ROUND:
case XMLTEXT:
min = 1; min = 1;
max = 2; max = 2;
break; break;
...@@ -1640,7 +1646,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1640,7 +1646,7 @@ public class Function extends Expression implements FunctionCall {
break; break;
case XMLNODE: case XMLNODE:
min = 1; min = 1;
max = 3; max = 4;
break; break;
case FORMATDATETIME: case FORMATDATETIME:
case PARSEDATETIME: case PARSEDATETIME:
......
...@@ -571,11 +571,26 @@ public class StringUtils { ...@@ -571,11 +571,26 @@ public class StringUtils {
* @return the node * @return the node
*/ */
public static String xmlNode(String name, String attributes, String content) { public static String xmlNode(String name, String attributes, String content) {
return xmlNode(name, attributes, content, true);
}
/**
* Create an XML node with optional attributes and content. The data is
* indented with 4 spaces if it contains a newline character and the indent
* parameter is set to true.
*
* @param name the element name
* @param attributes the attributes (may be null)
* @param content the content (may be null)
* @param indent whether to indent the content if it contains a newline
* @return the node
*/
public static String xmlNode(String name, String attributes, String content, boolean indent) {
String start = attributes == null ? name : name + attributes; String start = attributes == null ? name : name + attributes;
if (content == null) { if (content == null) {
return "<" + start + "/>\n"; return "<" + start + "/>\n";
} }
if (content.indexOf('\n') >= 0) { if (indent && content.indexOf('\n') >= 0) {
content = "\n" + indent(content); content = "\n" + indent(content);
} }
return "<" + start + ">" + content + "</" + name + ">\n"; return "<" + start + ">" + content + "</" + name + ">\n";
...@@ -672,6 +687,17 @@ public class StringUtils { ...@@ -672,6 +687,17 @@ public class StringUtils {
* @return the escaped text * @return the escaped text
*/ */
public static String xmlText(String text) { public static String xmlText(String text) {
return xmlText(text, false);
}
/**
* Escapes an XML text element.
*
* @param text the text data
* @param escapeNewline whether to escape newlines
* @return the escaped text
*/
public static String xmlText(String text, boolean escapeNewline) {
int length = text.length(); int length = text.length();
StringBuilder buff = new StringBuilder(length); StringBuilder buff = new StringBuilder(length);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
...@@ -694,6 +720,14 @@ public class StringUtils { ...@@ -694,6 +720,14 @@ public class StringUtils {
break; break;
case '\r': case '\r':
case '\n': case '\n':
if (escapeNewline) {
buff.append("&#x").
append(Integer.toHexString(ch)).
append(';');
} else {
buff.append(ch);
}
break;
case '\t': case '\t':
buff.append(ch); buff.append(ch);
break; break;
......
...@@ -8916,6 +8916,18 @@ CALL XMLNODE('p', null, 'Hello World'); ...@@ -8916,6 +8916,18 @@ CALL XMLNODE('p', null, 'Hello World');
> <p>Hello World</p> > <p>Hello World</p>
> rows: 1 > rows: 1
SELECT XMLNODE('p', null, 'Hello' || chr(10) || 'World') X;
> X
> ---------------------
> <p> Hello World </p>
> rows: 1
SELECT XMLNODE('p', null, 'Hello' || chr(10) || 'World', false) X;
> X
> -------------------
> <p>Hello World</p>
> rows: 1
CALL XMLCOMMENT('Test'); CALL XMLCOMMENT('Test');
> STRINGDECODE('<!-- Test -->\n') > STRINGDECODE('<!-- Test -->\n')
> ------------------------------- > -------------------------------
...@@ -8958,6 +8970,18 @@ CALL XMLTEXT('<test>'); ...@@ -8958,6 +8970,18 @@ CALL XMLTEXT('<test>');
> &lt;test&gt; > &lt;test&gt;
> rows: 1 > rows: 1
CALL XMLTEXT('hello' || chr(10) || 'world');
> STRINGDECODE('hello\nworld')
> ----------------------------
> hello world
> rows: 1
CALL XMLTEXT('hello' || chr(10) || 'world', true);
> 'hello&#xa;world'
> -----------------
> hello&#xa;world
> rows: 1
create memory table test(id int primary key, name varchar(255)); create memory table test(id int primary key, name varchar(255));
> ok > ok
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论