如何编写一个 PL/SQL 程序来打印出看起来像 xml 格式的字符串
Posted
技术标签:
【中文标题】如何编写一个 PL/SQL 程序来打印出看起来像 xml 格式的字符串【英文标题】:How write a PL/SQL program that prints out string which looking like xml format 【发布时间】:2017-07-14 07:49:42 【问题描述】:输入字符串:“a4b4c2d9d9c2e6e6b4s2o1o1s2a4w2r8r8k3g5g5k3w2” 我尝试了此代码作为第一步:
declare
word varchar2(50) := 'a4b4c2d9d9c2e6e6b4s2o1o1s2a4w2r8r8k2g5g5k2w2';
num number := length(word)/2;
name_array dbms_sql.varchar2_table;
begin
dbms_output.put_line(word);
FOR i IN 1..num LOOP
name_array(i) := substr(word, -2*i, 2);
END LOOP;
FOR i IN name_array.FIRST .. name_array.LAST LOOP
dbms_output.put_line(name_array(i));
END LOOP;
end;
此代码仅创建一个字符串数组。不是xml格式。我需要这个输出:
我需要使用哪些 SQL 函数、条件子句...?
【问题讨论】:
我在所需的输出中没有看到 XML 标记。 标签是什么?价值观是什么?它是从任何桌子上挑选出来的吗? @Serg ı 只需要一个看起来像 xml 格式的输出。这是关于字母的对齐和必要空格的确定。 @Dawn 不是从任何表中挑选的,我只是输入字符串值。这些都是我找到解决方案的信息。我知道这还不够 很可能是堆栈编程练习。您需要在解析下一个项目时扩展/修剪的开放节点集合。见docs.oracle.com/cd/B28359_01/appdev.111/b28370/… 【参考方案1】:Oracle 设置:
CREATE OR REPLACE TYPE CHARS_TABLE IS TABLE OF CHAR(2);
/
CREATE OR REPLACE TYPE INTEGERS_TABLE IS TABLE OF INTEGER;
/
PL/SQL:
这假定了一组格式良好的字符对,并且只是将每对缩进到适当的级别:
DECLARE
word VARCHAR2(50) := 'a4b4c2d9d9c2e6e6b4s2o1o1s2a4w2r8r8k2g5g5k2w2';
num PLS_INTEGER := LENGTH( word ) / 2;
name_array CHARS_TABLE := CHARS_TABLE();
depth_array INTEGERS_TABLE := INTEGERS_TABLE();
open_array INTEGERS_TABLE := INTEGERS_TABLE();
BEGIN
name_array.EXTEND( num );
depth_array.EXTEND( num );
open_array.EXTEND( num );
name_array(1) := SUBSTR( word, 1, 2 );
depth_array(1) := 1;
open_array(1) := 1;
FOR i IN 2 .. num LOOP
name_array(i) := SUBSTR( word, 2*i - 1, 2 );
open_array(i) := 1;
FOR j IN 1 .. i-1 LOOP
IF name_array(j) = name_array(i) THEN
open_array(i) := -open_array(i);
END IF;
END LOOP;
depth_array(i) := depth_array(i-1) + open_array(i);
END LOOP;
FOR i IN 1 .. num LOOP
FOR j IN 2 .. depth_array(i) + CASE open_array(i) WHEN 1 THEN 0 ELSE 1 END LOOP
DBMS_OUTPUT.PUT( ' ' );
END LOOP;
DBMS_OUTPUT.PUT_LINE( name_array(i) );
END LOOP;
END;
/
输出:
a4
b4
c2
d9
d9
c2
e6
e6
b4
s2
o1
o1
s2
a4
w2
r8
r8
k2
g5
g5
k2
w2
更新 - 更简单的基于堆栈的版本:
DECLARE
word CONSTANT VARCHAR2(50) := 'a4b4c2d9d9c2e6e6b4s2o1o1s2a4w2r8r8k2g5g5k2w2';
num CONSTANT PLS_INTEGER := LENGTH( word ) / 2;
name_array CHARS_TABLE := CHARS_TABLE();
depth PLS_INTEGER := 0;
name CHAR(2);
PROCEDURE indent( depth PLS_INTEGER, name CHAR )
IS
BEGIN
FOR j IN 2 .. depth LOOP
DBMS_OUTPUT.PUT( ' ' );
END LOOP;
DBMS_OUTPUT.PUT_LINE( name );
END;
BEGIN
name_array.EXTEND( num );
FOR i IN 1 .. num LOOP
name := SUBSTR( word, 2*i - 1, 2 );
IF depth > 0 AND name = name_array(depth) THEN
indent(depth,name);
depth := depth - 1;
ELSE
depth := depth - 1;
name_array(depth) := name;
indent(depth,name);
END IF;
END LOOP;
END;
/
【讨论】:
非常感谢 :) 我需要更多帮助。如何反转输出?我的意思是你的输出以 a4 b4 c2 d9.. 开头.. 但我的输出 w2 k3 g5.. .@MT0 @ecenurozturk 看看你的问题和我的回答中的SUBSTR()
电话之间的区别。【参考方案2】:
DECLARE
vs_CurrentChar VARCHAR2(1);
vs_NextChar VARCHAR2(1);
vs_TempText VARCHAR2(100);
vs_InputText VARCHAR2(100) := 'abcdffdcba';
vn_LengthOfText NUMBER := 1;
vn_WhileIndex NUMBER := 1;
vs_Spaces VARCHAR(100);
BEGIN
vs_TempText := NULL;
vs_CurrentChar := substr(vs_InputText, vn_WhileIndex, vn_LengthOfText);
dbms_output.put_line(vs_CurrentChar);
WHILE vn_WhileIndex < length(vs_InputText) - 1 LOOP
vs_NextChar := substr(vs_InputText, vn_WhileIndex + 1, vn_LengthOfText);
EXIT WHEN vs_CurrentChar = vs_NextChar;
vs_TempText := vs_TempText || vs_CurrentChar;
vs_CurrentChar := vs_NextChar;
vs_Spaces := NULL;
FOR i IN 1 .. vn_WhileIndex LOOP
vs_Spaces := vs_Spaces || chr(9); --'*';
END LOOP;
dbms_output.put_line(vs_Spaces || vs_CurrentChar);
vn_WhileIndex := vn_WhileIndex + 1;
END LOOP;
dbms_output.put_line(vs_Spaces || vs_CurrentChar);
FOR i IN 1 .. length(vs_TempText) LOOP
vs_Spaces := substr(vs_Spaces, vn_LengthOfText, length(vs_Spaces) - 1);
vs_CurrentChar := substr(vs_TempText, -i, vn_LengthOfText);
dbms_output.put_line(vs_Spaces || vs_CurrentChar);
END LOOP;
END;
/
并输出:
a
b
c
d
f
f
d
c
b
a
甚至,如果你把 '*'; 而不是 chr(9); 那么输出将如下所示:
a
*b
**c
***d
****f
****f
***d
**c
*b
a
【讨论】:
以上是关于如何编写一个 PL/SQL 程序来打印出看起来像 xml 格式的字符串的主要内容,如果未能解决你的问题,请参考以下文章