CONNECT xml_demo/xml_demo /* ** +---------------------------------------------+ ** | CREATE TABLE: xml_documents | ** +---------------------------------------------+ */ DROP TABLE xml_documents / CREATE TABLE xml_documents ( docname VARCHAR2(500) , xmldoc CLOB , timestamp DATE ) LOB (xmldoc) STORE AS xml_documents_lob ( TABLESPACE xml_docs STORAGE ( initial 1M next 1M pctincrease 0 maxextents UNLIMITED ) INDEX xml_documents_idx ) TABLESPACE xml_demod STORAGE ( INITIAL 256K NEXT 256K MINEXTENTS 1 MAXEXTENTS 121 PCTINCREASE 0 ) / ALTER TABLE xml_documents ADD CONSTRAINT xml_documents_pk PRIMARY KEY(docname) USING INDEX TABLESPACE xml_demox STORAGE ( INITIAL 64K NEXT 64K MINEXTENTS 1 MAXEXTENTS 121 PCTINCREASE 0 ) / ALTER TABLE xml_documents MODIFY ( xmldoc CONSTRAINT xml_documents_nn1 NOT NULL ) / /* ** +---------------------------------------------+ ** | CREATE TRIGGER: xml_documents_timestamp | ** +---------------------------------------------+ */ CREATE OR REPLACE TRIGGER xml_documents_timestamp BEFORE INSERT OR UPDATE on xml_documents FOR EACH ROW BEGIN :new.timestamp := sysdate; END; / /* ** +---------------------------------------------+ ** | CREATE DIRECTORY: xmlfiles | ** +---------------------------------------------+ */ DROP DIRECTORY "XMLFILES" / CREATE DIRECTORY "XMLFILES" AS '/u01/app/oracle/xml/testing' / /* ** +---------------------------------------------+ ** | CREATE PROCEDURE: insertXmlFile | ** | - Inserting and External XML File into | ** | a CLOB. | ** +---------------------------------------------+ */ CREATE OR REPLACE PROCEDURE insertXmlFile ( dir VARCHAR2 , file VARCHAR2 , name VARCHAR2 := NULL) IS theBFile BFILE; theCLob CLOB; theDocName VARCHAR2(500) := NVL(name, file); BEGIN -- (1) Insert a new row into xml_documents with an empty CLOB, and -- (2) Retrieve the empty CLOB into a variable with RETURNING ... INTO INSERT INTO xml_documents (docname, xmldoc) VALUES (theDocName, empty_clob()) RETURNING xmldoc INTO theCLob; DBMS_OUTPUT.PUT_LINE('SETTING: theDocName: ' || theDocName); DBMS_OUTPUT.PUT_LINE('SETTING: dir: ' || dir); DBMS_OUTPUT.PUT_LINE('SETTING: file: ' || file); -- (3) Get a BFile handle to the external file theBFile := BFileName(dir, file); -- (4) Open the file DBMS_LOB.fileOpen(theBFile); -- (5) Copy the contents of the BFile into the empty CLOB DBMS_LOB.loadFromFile( dest_lob => theCLob , src_lob => theBFile , amount => DBMS_LOB.getLength(theBFile)); -- (6) Close the file and commit DBMS_LOB.fileClose(theBFile); COMMIT; END; / show errors /* ** +---------------------------------------------+ ** | CREATE PROCEDURE: checkXMLInCLob | ** | - Checking the Well-Formedness of XML in | ** | CLOB. | ** +---------------------------------------------+ */ CREATE OR REPLACE PROCEDURE checkXMLInCLOB ( c CLOB , wellFormed OUT BOOLEAN , error OUT VARCHAR2) IS parser xmlparser.Parser; xmldoc xmldom.DOMDocument; XMLParserError EXCEPTION; PRAGMA EXCEPTION_INIT( XMLParserError, -20100 ); BEGIN parser := xmlparser.newParser; xmlparser.ParseCLOB(parser, c); xmlparser.freeParser(parser); wellFormed := TRUE; EXCEPTION WHEN XMLParserError THEN xmlparser.freeParser(parser); wellFormed := FALSE; error := SQLERRM; END; / show errors /* ** +---------------------------------------------+ ** | CREATE FUNCTION: idAttributeOfDocElement | ** | - Parsing XML from a String and Using | ** | DOM. | ** +---------------------------------------------+ */ CREATE OR REPLACE FUNCTION idAttributeOfDocElement ( xmldoc VARCHAR2 ) RETURN VARCHAR2 IS theXmlDoc xmldom.DOMDocument; theDocElt xmldom.DOMElement; retval VARCHAR2(400); XMLParseError EXCEPTION; PRAGMA EXCEPTION_INIT( XMLParseError, -20100 ); -- Local parse function keeps code cleaner. Return NULL if parse fails. FUNCTION parse (xml VARCHAR2) return xmldom.DOMDocument IS retDoc xmldom.DOMDocument; parser xmlparser.Parser; BEGIN parser := xmlparser.newParser; xmlparser.parseBuffer(parser,xml); retDoc := xmlparser.getDocument(parser); xmlparser.freeParser(parser); RETURN retdoc; EXCEPTION -- if the parse fails, we'll jump here WHEN XMLParseError THEN xmlparser.freeParser(parser); RETURN retdoc; END; BEGIN -- Parse the XML document passed in the VARCHAR2 argument theXmlDoc := parse(xmldoc); -- If the XML Document returned is no NULL... IF NOT xmldom.IsNull(theXmlDoc) THEN -- Get the outermost enclosing element (aka "Document Element") theDocElt := xmldom.getDocumentElement(theXmlDoc); -- Get the value of the document element's "id" attribute retval := xmldom.getAttribute(theDocElt, 'id'); -- Free the memory used by the parsed XML Document xmldom.freeDocument(theXmlDoc); RETURN retval; ELSE RETURN NULL; END IF; END; / show errors /* ** +---------------------------------------------+ ** | CREATE TABLE: message | ** | - Table to store sample (small) XML Docs. | ** +---------------------------------------------+ */ DROP TABLE message / CREATE TABLE message ( recipient VARCHAR2(80) , xml_message VARCHAR2(4000) ) / INSERT INTO message VALUES ('Jeff', 'Montgomery BurnsRelease the Hounds!') / INSERT INTO message VALUES ('Melody', 'Montgomery BurnsRelease the Hounds!') / INSERT INTO message VALUES ('Alex', 'Montgomery BurnsRelease the Hounds!') / COMMIT;