如何在Oracle 11g r2中简单地更改XMLTYPE的节点属性值?

时间:2010-10-25 08:11:09

标签: oracle plsql

我只想更改此XML(包含在XMLTYPE变量中)所有名为“ChildNode”的节点,其中“Name”=“B”属性值为“C”:

<RootNode>
  <ChildNodes>
    <ChildNode Name="A"/>
    <ChildNode Name="B"/>
  </ChildNodes>
</RootNode>

DECLARE
  FXML XMLTYPE;
BEGIN
  FXML := ...; -- see text before
  -- what next?
END;

谢谢!

4 个答案:

答案 0 :(得分:5)

您可以使用updatexml功能:

declare
  fOrigXml XmlType := XmlType(
'<RootNode>
  <ChildNodes>
    <ChildNode Name="A"/>
    <ChildNode Name="B"/>
  </ChildNodes>
</RootNode>');
   fResXml XmlType;
begin
  select updatexml((fOrigXml), '/RootNode/ChildNodes/ChildNode[@Name="B"]/@Name', 'C') into fResXml from dual;
end;

答案 1 :(得分:0)

这是一个解决方案:

Declare
    xml_nl           DBMS_XMLDOM.DOMNodeList;
    xml_node         DBMS_XMLDOM.DOMNode;
    xml_doc          DBMS_XMLDOM.DOMDocument;
    v_xml_clob       CLOB;
    v_name           VARCHAR2(32767);
    v_xml            VARCHAR2(32767) := 
      '<RootNode>
        <ChildNodes>
          <ChildNode Name="A"/>
          <ChildNode Name="B"/>
        </ChildNodes>
      </RootNode>';
Begin
    xml_doc := DBMS_XMLDOM.NewDOMDocument(XMLType.createXML(v_xml));
    xml_nl  := DBMS_XMLDOM.GetElementsByTagName(xml_doc, 'ChildNode');
    FOR i IN 0 .. (DBMS_XMLDOM.getLength(xml_nl) - 1) LOOP
      xml_node := DBMS_XMLDOM.Item(xml_nl, i);

      DBMS_XSLPROCESSOR.valueOf(xml_node, '@Name', v_name);
      IF v_name IS NOT NULL AND v_name = 'B' THEN
        DBMS_XMLDOM.setAttribute(DBMS_XMLDOM.makeElement(xml_node), 'Name', 'C');
      END IF;
    END LOOP;
    DBMS_LOB.createTemporary(v_xml_clob, cache => FALSE);
    DBMS_LOB.Open(v_xml_clob, DBMS_LOB.lob_readwrite);
    DBMS_XMLDOM.writeToCLob(xml_doc, v_xml_clob);
    DBMS_OUTPUT.put_line(v_xml_clob);
End;

答案 2 :(得分:0)

还有一个:

SET SERVEROUTPUT ON;
DECLARE
  DOC DBMS_XMLDOM.DOMDocument;
  var XMLTYPE := XMLType('<RootNode>  
<ChildNodes>    
<ChildNode Name="A"/>    
<ChildNode Name="B"/>  
</ChildNodes>
</RootNode>');
xmlvalue CLOB;
PROCEDURE changeNameAttributes(
    DOC dbms_xmldom.domdocument)
IS
  nl dbms_xmldom.domnodelist;
  v_clob CLOB;
  LEN NUMBER;
  n dbms_xmldom.domnode;
  nodename  VARCHAR2(4000);
  nodevalue VARCHAR2(4000);
PROCEDURE changeAttributeB(
    n dbms_xmldom.domnode)
IS
  e dbms_xmldom.domelement;
  dn dbms_xmldom.domnode;
  nnm dbms_xmldom.domnamednodemap;
  attrname VARCHAR2(100);
  attrval  VARCHAR2(100);
  LEN      NUMBER;
BEGIN
  e                    := dbms_xmldom.makeelement(n); -- get all attributes of element
  nnm                  := xmldom.getattributes(n);
  IF(xmldom.isnull(nnm) = FALSE) THEN
    LEN                := dbms_xmldom.getlength(nnm); -- loop through attributes
    FOR i              IN 0 .. LEN -1
    LOOP
      dn       := dbms_xmldom.item(nnm, i);
      attrname := dbms_xmldom.getnodename(dn);

      IF(attrname = 'Name' ) THEN
       attrval  := dbms_xmldom.getnodevalue(dn);    
      IF(attrval = 'B') THEN
      dbms_xmldom.setnodevalue(dn,'C');
      END IF;
      END IF;      
    END LOOP;
  END IF;
END changeAttributeB;
BEGIN
  nl    := dbms_xmldom.getelementsbytagname(DOC, '*');
  LEN   := dbms_xmldom.getlength(nl);
  FOR i IN 0 .. LEN -1
  LOOP
    n        := dbms_xmldom.item(nl, i);
    nodename := dbms_xmldom.getnodename(n);
    IF ( nodename = 'ChildNode') THEN   
    changeAttributeB(n);   
    END IF;
  END LOOP;
END changeNameAttributes;
BEGIN
  DOC := DBMS_XMLDOM.newDOMDocument(var); 
  --Before
   DBMS_OUTPUT.PUT_LINE('BEFORE');
    DBMS_LOB.createtemporary (xmlvalue, TRUE);
  DBMS_XMLDOM.writeToClob(DOC, xmlvalue);
  DBMS_OUTPUT.PUT_LINE(xmlvalue); 
  -- Modify
  changeNameAttributes(DOC);  
 -- After
  DBMS_OUTPUT.PUT_LINE('AFTER');
  DBMS_XMLDOM.writeToClob(DOC, xmlvalue);
  DBMS_OUTPUT.PUT_LINE(xmlvalue);
  dbms_xmldom.freedocument(DOC); 
END;
/

答案 3 :(得分:-1)

/* Formatted on 6/19/2016 3:02:05 PM (QP5 v5.126) */
DECLARE
    var         XMLTYPE;
    doc         DBMS_XMLDOM.domdocument;
    ndoc        DBMS_XMLDOM.domnode;
    docelem     DBMS_XMLDOM.domelement;
    node        DBMS_XMLDOM.domnode;
    childnode   DBMS_XMLDOM.domnode;
    nodelist    DBMS_XMLDOM.domnodelist;
    nodelist2   DBMS_XMLDOM.domnodelist;
    buf         VARCHAR2 (2000);

    newnode     DBMS_XMLDOM.domnode;
    clonenode   DBMS_XMLDOM.domnode;
    elem        DBMS_XMLDOM.domelement;

    PROCEDURE duyethoiquy (clonenode IN OUT DBMS_XMLDOM.domnode)
    IS
        childnode                 DBMS_XMLDOM.domnode;
        simpletypechildnodemap    DBMS_XMLDOM.domnamednodemap;
        simpletypeattributenode   DBMS_XMLDOM.domnode;
    BEGIN
        -- xu ly clonenode nay
        -- sau do lay may con de duyet tiep
        -- thay doi node con lev 1..

        IF NOT DBMS_XMLDOM.isnull (clonenode)
        THEN
            -- xu ly node nay
            -- thay doi mot vai thuoc tinh cua cay nay
            simpletypechildnodemap := DBMS_XMLDOM.getattributes (clonenode);
            simpletypeattributenode :=
                DBMS_XMLDOM.getnameditem (simpletypechildnodemap, 'r');

            IF NOT DBMS_XMLDOM.isnull (simpletypeattributenode)
            THEN
                DBMS_XMLDOM.setnodevalue (simpletypeattributenode, '');

                DBMS_XMLDOM.writetobuffer (simpletypeattributenode, buf);
                DBMS_OUTPUT.put_line ('attr:' || buf);
            END IF;


            IF DBMS_XMLDOM.haschildnodes (clonenode)
            THEN
                childnode := DBMS_XMLDOM.getfirstchild (clonenode);

                --- ghi nhan gia tri
                WHILE NOT DBMS_XMLDOM.isnull (childnode)
                LOOP
                    -- xu ly con cua no:
                    duyethoiquy (childnode);


                    childnode := DBMS_XMLDOM.getnextsibling (childnode);
                -------------------------------------

                END LOOP;
            ELSE                                                    -- is leaf
                -- reset gia tri cua node duoc clone nay roi
                DBMS_XMLDOM.setnodevalue (clonenode, '');
            END IF;
        END IF;
    END;
BEGIN
    var :=
        xmltype('<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
 xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac"
 xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">
 <sheetData>
    <row r="1"><c r="A1" s="2" t="s"><v>0</v></c><c r="B1" s="2" t="s"><v>0</v></c></row>
    <row r="3"><c r="A3" s="2" t="s"><v>1</v></c><c r="B3" s="2" t="s"><v>1</v></c></row>
 </sheetData>
</worksheet>');

    -- Create DOMDocument handle:

    ndoc :=
        DBMS_XMLDOM.makenode(DBMS_XMLDOM.getdocumentelement (
                                 DBMS_XMLDOM.newdomdocument (var)));

    newnode :=
        DBMS_XMLDOM.makenode(DBMS_XMLDOM.getdocumentelement(DBMS_XMLDOM.newdomdocument(xmltype('<row r="2"><c r="A2" s="1" t="s"><v>0</v></c></row>'))));
    -- ghi vao node
    nodelist := DBMS_XSLPROCESSOR.selectnodes (ndoc, '/worksheet/sheetData');

    IF NOT DBMS_XMLDOM.isnull (nodelist)
    THEN
        node := DBMS_XMLDOM.item (nodelist, 0);

        childnode := DBMS_XMLDOM.getlastchild (node);



        clonenode := DBMS_XMLDOM.clonenode (childnode, TRUE);

        -- thay doi node cha
        duyethoiquy (clonenode);


        --  DBMS_XMLDOM.writetobuffer (newnode, buf);
        --  DBMS_OUTPUT.put_line ('LastChild:' || buf);

        elem :=
            DBMS_XMLDOM.makeelement(DBMS_XMLDOM.appendchild (
                                        node,
                                        DBMS_XMLDOM.makenode(DBMS_XMLDOM.makeelement(DBMS_XMLDOM.importnode (
                                                                                         DBMS_XMLDOM.getownerdocument(node),
                                                                                         clonenode, --newnode,
                                                                                         TRUE)))));
    END IF;

    DBMS_XMLDOM.writetobuffer (ndoc, buf);
    DBMS_OUTPUT.put_line ('After:' || buf);
END;

- vi du voi xm;