如何写一个PL / SQL程序打印出看起来像xml格式的字符串

时间:2017-07-14 07:49:43

标签: oracle plsql

输入字符串:“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格式。我需要这个输出:

ı need this output:

我需要使用哪些SQL函数,条件子句?

2 个答案:

答案 0 :(得分:0)

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;
/

答案 1 :(得分:0)

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