将属性添加到xmltype,其值取自序列

时间:2013-09-12 20:10:17

标签: xml oracle xmltype

我在版本11.2中使用Oracle XE。

我有这样的XML:

<root>
    <x a="a"/>
    <x a="b"/>
    <x a="c"/>
</root>

不,我想将属性b添加到每个元素x,其值取自序列,但它应为每个元素获取新值。预期结果是:

<root>
    <x a="a" b="1"/>
    <x a="b" b="2"/>
    <x a="c" b="3"/>
</root>

我发现要向XML添加属性我可以使用insertchildxml,但是在将序列中的相同(frist)值添加到所有属性b中。我找不到如何为每个单独的元素x调用此函数。

我将不胜感激任何帮助。

2 个答案:

答案 0 :(得分:1)

我终于找到了一些解决方案,关键是使用XMLTable()函数。这是我的代码:

declare
v_inXML xmltype;
  v_tmpXML xmltype;
  v_withIdXML xmltype;
  v_outXML xmltype;
BEGIN   
  v_inXML := XMLType('<root><x a="a"/><x a="b"/><x a="c"/></root>');
  v_withIdXML := XMLType('<root/>'); 
  v_outXML := XMLType('<root/>');

  for c_rec in (
    select *
    from   XMLTable('for $i in /root/x
          return $i'
          passing  v_inXML
          columns x xmltype path '/x'
    )
  )
  loop
    select insertchildxml(c_rec.x,'//x', '@b', pckg_ent_pk_seq.nextval) into v_tmpXML from dual;      
    select insertchildxml(v_withIdXML, '/root', 'x', v_tmpXML) into v_withIdXML from dual;    
  end loop;

  select updatexml(v_outXML, '/root', v_withIdXML) into v_outXML from dual;

  dbms_output.put_line(v_outXML.getClobVal());
END;

结果是:

<root><x a="a" b="92"/><x a="b" b="93"/><x a="c" b="94"/></root>

答案 1 :(得分:0)

这可以通过各种方式完成。选择取决于如何构建源数据,所需的输出格式等。

<强> 1。 XSLT转型

使用XMLTransform()功能添加属性。

SQLFiddle test

  with params as (
    select 
      XMLParse( content
        '
        <root>
            <x a="a"/>
            <x a="b"/>
            <x a="c"/>
        </root>                  
        '
      ) as doc_field
    from dual
  )
  select
    XMLTransform( 
      doc_field,
      XMLParse( content
        ' 
        <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="/">    
           <root>
           <xsl:for-each select="child::*">
             <xsl:apply-templates></xsl:apply-templates> 
           </xsl:for-each>
           </root>
        </xsl:template>
          <xsl:template match="x">
              <x  a="{@a}" b="{position()}" />
          </xsl:template>
        </xsl:stylesheet>
        '
      )
    )
  from params

<强> 2。 XQuery返回单个XML

使用XMLQuery()函数可以将单个XML转换为另一个,与上面基本相同的变体。

SQLFiddle test

with params as (
  select 
    XMLParse( content
      '
      <root>
          <x a="a"/>
          <x a="b"/>
          <x a="c"/>
      </root>                  
      '
    ) as doc_field
  from dual
)
select
  XMLQuery( 
    '
      <root>
      {
        for $x at $pos in $doc/root/x
        return <x a="{$x/@a}" b="{$pos}" />
      }
      </root>
    '
    passing doc_field as "doc"
    returning content
  )
from params

第3。从行的顺序获取值

这种方法可以更好地匹配必须在运行中构造XML并且可以在构造阶段注入序列属性值的情况。

SQLFiddle test

with params as (
  select 'a' a from dual union all
  select 'b' a from dual union all
  select 'c' a from dual 
)
select
  XMLElement("root",
    XMLAgg(
      XMLElement("x",
        XMLAttributes(
          a as "a",
          rownum as "b"
        )  
      )
    )
  )
from params

如果您将已经构建的XML分解为具有XMLTable()函数的记录,则最后一个方法也可以帮助构建XML。