1

我在 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但是将相同的(第一个)值从序列添加到所有属性b。我找不到如何为每个单独的元素调用此函数x

我将不胜感激任何帮助。

4

2 回答 2

2

我终于找到了一些解决方案,关键是使用 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>
于 2013-09-13T13:24:11.987 回答
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

如果您将其分解为具有XMLTable()功能的记录,最后一种方法也可以帮助处理已构建的 XML。

于 2013-09-13T10:25:32.210 回答