XMLTYPE ORA-31011:XML解析失败,没有根元素只有嵌套元素

时间:2017-08-29 20:39:12

标签: xml oracle oracle11g xml-serialization xmltype

我在oracle中有一个返回XMLType但没有root元素的函数,因为根元素可以重复,我需要在另一个选择中使用XMLElements

我的功能简化为:

CREATE OR REPLACE FUNCTION F_XML_WITHOUT_ROOT 
RETURN XMLTYPE AS 

  vXML CLOB;
  vXML_TEMP CLOB;

BEGIN
  vXML := '';

  FOR cI IN (
    SELECT
      '10' ALM_IN_CODIGO,
      '1' LOC_IN_CODIGO,
      'DE' NAT_ST_CODIGO
    FROM DUAL
    UNION ALL
    SELECT
      '10' ALM_IN_CODIGO,
      '2' LOC_IN_CODIGO,
      'DE' NAT_ST_CODIGO
    FROM DUAL
  ) LOOP

    SELECT
      (
        XMLSerialize(content
          XMLElement("Item" 
            , XMLForest(
                cI.ALM_IN_CODIGO AS ALM
              , cI.LOC_IN_CODIGO AS LOC
              , cI.NAT_ST_CODIGO AS NAT
            ) Item
          ).extract('/*') indent
        ) 
      ) XML_BL_XML
      INTO vXML_TEMP
      FROM DUAL;

    vXML := vXML || vXML_TEMP;

  END LOOP;

  RETURN XMLTYPE.CreateXML(vXML);
END F_XML_WITHOUT_ROOT;

当我打电话给你时:

SELECT
MGCLI.F_XML_WITHOUT_ROOT()
FROM DUAL;

我收到了错误代码

ORA-31011: XML parsing failed

我认为有更好的方法来完成这项工作,但我不确定如何

<Item><ALM>10</ALM><LOC>1</LOC><NAT>DE</NAT></Item>
<Item><ALM>10</ALM><LOC>2</LOC><NAT>DE</NAT></Item>

正确的功能是在此选择中调用以生成整个XML

 SELECT
 XMLSerialize(content
    XMLElement("Group", XMLAttributes('I' AS "OP")
    , XMLForest(
          3 FIL
        , 59 TPD
    ) 
    , XMLElement("Obs"
        , XMLForest(
          'N' OB_CH_TYPE
          , (
            'Ref. '
          ) OB_ST_OBS
        )
      )
      , (
        SELECT
          XMLAgg(
            XMLElement("Item", XMLAttributes('I' AS "OP")
              , XMLElement("ITN",1)
              , MGCLI.F_XML_WITHOUT_ROOT()
            )
          ) FROM DUAL
        )       
      ).extract('/*') indent
    ) XML_BL_XML
        FROM DUAL
        ;

2 个答案:

答案 0 :(得分:0)

XML文档必须只有一个根元素,否则它们格式不正确,并且需要兼容的XML解析器将此类问题报告为错误。

通过将多个元素包装在单个根元素中来修复XML。

答案 1 :(得分:0)

我得到一种方法来制作我想要的东西:

我更改了功能:

create or replace FUNCTION F_XML_WITHOUT_ROOT 
RETURN sys_refcursor AS 

  refC sys_refcursor;
BEGIN

  OPEN refC FOR
    SELECT
      '10' ALM,
      '1' LOC,
      'DE' NAT
    FROM DUAL
    UNION ALL
    SELECT
      '10' ALM,
      '2' LOC,
      'DE' NAT
    FROM DUAL
  ;

  RETURN refC;
END F_XML_WITHOUT_ROOT;

然后我更改主SELECT以生成整个XML:

选择      ResultSet.getString(column含量

    XMLElement("Group", XMLAttributes('I' AS "OP")
    , XMLForest(
          3 FIL
        , 59 TPD
    ) 
    , XMLElement("Obs"
        , XMLForest(
          'N' OB_CH_TYPE
          , (
            'Ref. '
          ) OB_ST_OBS
        )
      )

      , (
        SELECT
          XMLAgg(
            XMLElement("Item", XMLAttributes('I' AS "OP")
              , XMLElement("ITN",1)
              , 
              (SELECT
                XMLAgg(
                  XMLElement("Item", 
                     XMLElement("ALM", ALM) 
                    ,XMLElement("LOC", LOC)
                    ,XMLElement("NAT", NAT)
                  )
                ) 
                FROM 
                XMLTABLE(
                  '/ROWSET/ROW'
                  PASSING XMLType(MGCLI.F_XML_WITHOUT_ROOT())
                  COLUMNS
                  ALM  PATH 'ALM',
                  LOC PATH 'LOC',
                  NAT PATH  'NAT'
                )
              ) 
            )
          ) FROM DUAL
        )

      ).extract('/*') indent
    ) XML_BL_XML
        FROM DUAL;

结果:

<Group OP="I">
  <FIL>3</FIL>
  <TPD>59</TPD>
  <Obs>
    <OB_CH_TYPE>N</OB_CH_TYPE>
    <OB_ST_OBS>Ref. </OB_ST_OBS>
  </Obs>
  <Item OP="I">
    <ITN>1</ITN>
    <Item>
      <ALM>10</ALM>
      <LOC>1</LOC>
      <NAT>DE</NAT>
    </Item>
    <Item>
      <ALM>10</ALM>
      <LOC>2</LOC>
      <NAT>DE</NAT>
    </Item>
  </Item>
</Group>

这是我找到的最佳方式,也许还有另一种......