1. Trang chủ
  2. » Công Nghệ Thông Tin

Oracle XSQL- P15 pptx

20 150 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 20
Dung lượng 416,32 KB

Nội dung

261 Oracle can store any media type in the database—XML is no exception. In the previous pages, you saw how to query against XML documents stored in the database. This sec- tion examines how to return XML—as opposed to strings—into your XSQL. The first tool you’ll examine is the xsql:include-owa action, which allows you to write XML into the XSQL result. Next, you’ll learn about the XMLGEN utility. It essentially allows you to do what XSQL does—generate XML based on a SQL query. The difference is that you can generate XML from inside a PL/SQL procedure. The last section covers a new feature of Oracle 9i—the XMLType. This allows you to easily store and query XML doc- uments stored in Oracle. Before beginning the lessons, it’s important to understand what is hard about retrieving XML with XSQL. The first section covers these difficulties. What’s So Hard? In the previous section on Oracle Text, you saw that it is quite easy to store XML in the table. Just insert it like any other text. The size of our test documents was limited, but that is easily remedied—just use a CLOB type and you can store gigabytes of XML. You might be wondering, “Can’t you just select the text?” Retrieving XML CHAPTER 11 Well, you can, but not with the xsql:query action. Consider the following XSQL: <?xml version=”1.0”?> <page connection=”demo” xmlns:xsql=”urn:oracle-xsql”> <xsql:query> SELECT text FROM docs_table WHERE contains(text,’software INPATH (/article/body)’)>0 </xsql:query> </page> It will execute easily enough and return the result shown in Figure 11.1. It looks like XML, so what’s the problem? Upon closer examination, you’ll see that the XML returned by the query isn’t XML at all! Notice that Internet Explorer didn’t render it with the customary colored tags. When you look at the source, you’ll see that all of the essential XML characters have been escaped and replaced with their URL- encoded equivalents. What a shame! In the context of this example, it seems that you have uncovered a horrible failing of XSQL. But it isn’t, really. XSQL’s default behavior is to assume that XML isn’t being returned. Thus, it’s proper and required to escape the special XML characters. As you’ll see, the workarounds are pretty easy. In this chapter, you’ll learn about the PL/SQL-based workaround. You can also retrieve XML with the help of cus- tom XSQL action handlers, as you’ll see in Chapter 18, “Custom Action Handlers.” Figure 11.1 Result of retrieving XML with xsql:query. 262 Chapter 11 Creating XML with xsql:include-owa In Chapter 5, “Writing XSQL Pages,” you learned that you could use the xsql: include-owa to include XML of your own choosing in your result. At that point, PL/SQL hadn’t been covered, so you couldn’t explore this action in detail. Now you can. Here you’ll learn how to use the htp.print PL/SQL procedure to write XML of your own choosing to the XSQL datagram. First, however, you need to cover a little background. Oracle provides two packages, (1) htp and (2) htf, that have a series of procedures and functions, respectively. The original purpose of these was to allow PL/SQL developers to easily create Web appli- cations. For each HTML element there is both a wrapper procedure and wrapper func- tion. This XSQL executes the wrapper procedure for the italic tag. <?xml version=”1.0”?> <page connection=”demo” xmlns:xsql=”urn:oracle-xsql”> <xsql:include-owa> htp.italic(htf.bold(‘hello’)); </xsql:include-owa> </page> This will produce the output seen in Figure 11.2. The <I> tags are included in our XML result, and the angle brackets weren’t replaced with &lt; and &gt;. How do the htp and htf procedures escape escaping? The procedures in the htp package write to the server-side page buffer. Figure 11.2 Result of htp.italic and htf.bold. Retrieving XML 263 Here’s how the htp procedures and htf functions are able to get the angle brackets all the way through to the browser: ■■ The htf functions wrapper their argument with the appropriate tags and return the resultant string. In this case, hello is wrappered and <b>hello</b> is returned. ■■ The htp procedures also wrapper their argument. In this case, the wrappering produces <i><b>hello</b></i>. ■■ Instead of returning anything, the htp procedures write their result to the server-side page buffer. ■■ The xsql:include-owa action reads the contents of the server-side page buffer and writes those to the output without escaping the reserved XML characters. In all likelihood, you don’t have any interest in using the htp and htf subprograms to generate HTML for your XSQL. (If you do have a strong interest in creating such an architecture, consider taking a head-clearing walk. There be dragons!) From an XSQL standpoint, there is really one subprogram of interest—htp.print. The htp.prn procedure allows you to print an arbitrary string to the server-side page buffer without a trailing carriage return. (If you want a trailing carriage return, use htp.print.) You aren’t limited solely to HTML tags, and all of the angle brackets will stay intact. The following procedure works this magic: CREATE OR REPLACE PROCEDURE get_doc_xml IS doc_xml docs_table.text%TYPE; CURSOR doc_cursor IS SELECT text FROM docs_table WHERE contains(text,’software INPATH (/article/body)’)>0; BEGIN htp.prn(‘<article-set>’); OPEN doc_cursor; LOOP FETCH doc_cursor INTO doc_xml; EXIT WHEN doc_cursor%NOTFOUND; htp.prn(doc_xml); END LOOP; htp.print(‘</article-set>’); END; The procedure selects the articles that have the word “software” inside the body ele- ment of the XML documents. Before looping through the cursor, a start tag for the root element is printed to the buffer. This is required because the xsql:include-owa will return an error if the XML that you write isn’t well formed. In the loop itself, each doc- ument is written to the buffer and the loop exits at the end of the cursor. The final step is to close the root element. The procedure can be called with the following XSQL: <?xml version=”1.0”?> <page connection=”demo” xmlns:xsql=”urn:oracle-xsql”> <xsql:include-owa> 264 Chapter 11 get_doc_xml; </xsql:include-owa> </page> The result is an XML document that contains two XML documents stored in the database, as shown in Figure 11.3. In our example, the query was hard coded. As you learned earlier, however, you can easily make the queries completely dynamic and based on user input. Generating XML from PL/SQL From the previous section, you saw how to write a particular data field as XML. Of course, you can use the same methodology to create quite complex XML documents and write them to the XSQL output. If you want to do this, there are a couple of PL/SQL packages that can help you. These are discussed in this section. They allow you to do exactly what XSQL does, but from inside a procedure. This raises the obvi- ous and valid architectural question: Why would you want to generate XML from inside PL/SQL for consumption by XSQL? We’ll look at these valid concerns after learning a bit about the helper code available. Oracle 9i users can use the DBMS_QUERY package, while Oracle 8i users can use the XMLGEN package. Figure 11.3 XML documents in XSQL results. Retrieving XML 265 For Oracle 9i, the DBMS_QUERY package will XML-ify a query into a CLOB variable. You then break the CLOB into strings that can be passed to the http.prn procedure. CREATE OR REPLACE PROCEDURE use_dbms_xmlgen IS ctx dbms_xmlgen.ctxhandle; result_clob CLOB; output_var VARCHAR2(4000); offset_var INTEGER :=1; buf_size INTEGER:=4000; BEGIN ctx:=dbms_xmlgen.newContext(‘SELECT * FROM emp’); result_clob:=dbms_xmlgen.getXML(ctx); WHILE offset_var < dbms_lob.getlength(result_clob) LOOP DBMS_LOB.READ(result_clob,buf_size,offset_var,output_var); htp.prn(output_var); offset_var:=offset_var+4000; END LOOP; END; You call this procedure with the following XSQL: <?xml version=”1.0”?> <page connection=”demo” xmlns:xsql=”urn:oracle-xsql”> <xsql:include-owa> use_dbms_xmlgen; </xsql:include-owa> </page> At the Oracle 8i level, the code is slightly different: It doesn’t use contexts, and the SQL statement can be handed directly to the getXML procedure. However, the XMLGEN package has been deprecated. Oracle 9i users should use the DBMS_XMLGEN package instead. CREATE OR REPLACE use_xmlgen IS result_clob CLOB; output_var VARCHAR2(4000); offset_var INTEGER :=1; buf_size INTEGER:=4000; BEGIN result_clob:=xmlgen.getXML(‘SELECT * FROM emp’); WHILE offset_var < dbms_lob.getlength(result_clob) LOOP DBMS_LOB.READ(result_clob,buf_size,offset_var,output_var); htp.prn(output_var); offset_var:=offset_var+4000; END LOOP; END; 266 Chapter 11 In both of these cases, your result is going to look exactly the same as if you executed the SQL using the xsql:query element. The XML generated using these APIs is also in the canonical format. So, for these simple examples, you’ve done a lot of work in order to do what XSQL does anyway! In general, if you can get the same result using a straight XSQL query, then you probably should. Of course, with this methodology you can apply a lot of procedural logic, as you did with reference cursors a few pages ago. But then, you can probably accomplish the same logic using the xsql:ref-cursor-function action. It works great any time you wish to procedurally create the SQL statement whose results you want in XML. And again, if you can get the same result using xsql:ref -cursor-function, then you should employ that action instead. There are some cases where you will find use for the DBMS_XMLGEN (or XMLGEN) packages at the PL/SQL level. The key advantage is that you can assemble your XML at a very atomic level and have great control over it. You can dynamically select exactly the XML elements you wish to put into the output and base those decisions on any data you can access in the database. If you need to grab a couple of rows from the database, you can put them into the output with the htp.prn procedure discussed earlier. However, it’s important to remember that the DBMS_XMLGEN (or XMLGEN) packages used in this way are just one tool in your toolbox. You should probably keep it in the bottom of your toolbox and reach for xsql:query and xsql:ref-cursor -function. Also, you should understand action handlers before basing too much code on this approach. An action handler can also give you fine-grained control over the XML, as well as give you more precise ways of handling elements than the approach described here. XMLType In our earlier example with Oracle Text, you stored the XML as a simple string. Oracle 9i users can also store documents using the XMLType. The XMLType gives you much more power over your XML than you have with simple strings. There are two ways to use XMLType: (1) You can create an XMLType object at runtime based on a string or clob, or (2) you can create a column in the database of XMLType. Having an XMLType as a column is more efficient, so you’ll learn about this method first. However, it’s often impractical to do this, especially if you are working with existing database schemas. You’ll see how to construct and use the XMLType dynamically, also. This section con- cludes by detailing all the procedures and functions you can use in conjunction with XMLType. Here is how you get started. Your first step is to create a table that has an XMLType column. You can do that as follows: CREATE TABLE XMLType_table( ID NUMBER, DOC_NAME VARCHAR2(20), xml_doc SYS.XMLTYPE); Retrieving XML 267 Now you want to put some data in to your table. The only difference between this insert and the plain-text insert is the call to sys.XMLType.createXML. This changes the string data into the XMLType. INSERT INTO XMLType_table (id,doc_name,xml_doc) VALUES (1,’doc1’, sys.XMLType.createXML(‘<article> <subject>networking</subject> <title>Networking Basics</title> <body> People didn’’t notice the first fax machine. The second infinitely increased the value of both. </body> </article>’) ); INSERT INTO XMLType_table(id,doc_name,xml_doc) VALUES (2,’doc2’, sys.XMLType.createXML(‘<article> <subject>software</subject> <reference>Mythical Man Month, Dr. Fred Brooks</reference> <title>Brook’’s Law</title> <body>Putting more people on a late software project makes it later.</body> </article>’) ); As before, you have to create an index on your column, and you’ll have to update it every time that you update the data. However, you don’t have to create a section group first. Oracle already knows it’s dealing with XML. CREATE INDEX XMLType_index ON XMLType_table(xml_doc) INDEXTYPE IS ctxsys.context; At this point, you can do all of the types of searches that you did earlier with Oracle Text. Here is one example: SELECT xml_doc FROM XMLType_table WHERE contains(xml_doc,’people INPATH (/article/body)’)>0; Using the xsql:include-owa action, you can also use the htp.prn technique to push the document into the XSQL output. In this particular case, the documents are less than 4,000 characters, so you can use the getStringVal function. However, if the documents are larger, a runtime error would be generated. If there may be documents longer than 4,000 characters, you would have to iterate through a CLOB, as you did in the previous section. CREATE OR REPLACE get_XMLType_xml IS xml_doc_str VARCHAR2(4000); CURSOR doc_cursor IS 268 Chapter 11 SELECT a.xml_doc.getStringVal() FROM XMLType_table a WHERE CONTAINS(xml_doc,’people INPATH (/article/body)’)>0; BEGIN htp.print(‘<article-set>’); OPEN doc_cursor; LOOP FETCH doc_cursor INTO xml_doc_str; EXIT WHEN doc_cursor%NOTFOUND; htp.prn(xml_doc_str); END LOOP; htp.print(‘</article-set>’); END; At this point, you haven’t done anything more than you did when the XML was just plain text. The following example takes you into new territory. The extract function allows you to pull just the nodes you want from the document. By simply altering our cursor statement as follows: CURSOR doc_cursor IS SELECT a.xml_doc.extract(‘/article/subject’).getStringVal() FROM XMLType_table a WHERE CONTAINS(xml_doc,’people INPATH (/article/body)’)>0; you can get a result that just returns the subject nodes. But the getStringVal is still limited to 4,000 characters. If the node that you’re extracting (including the text, all the children, and all of the tags) contains more than 4,000 characters of data, a runtime error will be raised. With this simple SELECT statement you are solving a complex problem very ele- gantly. The relational model is great at storing structured data, such as a company’s payroll or accounts receivable, but has a hard time with unstructured document data. XML is great for formatting documents, but it is complex to store and search across sets of XML documents. By storing XML documents in the Oracle database, you get all of the benefits of the relational model plus the backup, recovery, and performance afforded by Oracle. By using Oracle Text in conjunction with the XMLType, you can easily search the documents and extract the nodes that you want. You’ll be seeing more of this lucrative combination in Chapter 14, “Building XSQL Web Applications,” when you build your first XSQL application from scratch. NOTE The extract function, along with several other functions and procedures of XMLType, uses XPath to search the document. You’ll learn more about XPath in the next chapters. In this case, you had XMLType set up at the database level. You can also instantiate XMLType at runtime. In the following example, you return to the docs_table used in the original examples of Oracle Text. In that table, the XML is stored simply as a Retrieving XML 269 [...]... the XMLType object is a fragment, 0 if it is well formed Retrieving XML Moving On This chapter showed you how you can access XML in your database Now, the coverage of the Oracle database is complete You’ve learned the basics of Oracle SQL, PL/SQL, Text, and now XML retrieval and how to use these technologies with XSQL Now that you’ve mastered data retrieval, the next step is to learn about presentation . code available. Oracle 9i users can use the DBMS_QUERY package, while Oracle 8i users can use the XMLGEN package. Figure 11.3 XML documents in XSQL results. Retrieving XML 265 For Oracle 9i, the. storing XML documents in the Oracle database, you get all of the benefits of the relational model plus the backup, recovery, and performance afforded by Oracle. By using Oracle Text in conjunction. version=”1.0”?> <page connection=”demo” xmlns:xsql=”urn :oracle- xsql”> <xsql:include-owa> use_dbms_xmlgen; </xsql:include-owa> </page> At the Oracle 8i level, the code is slightly different:

Ngày đăng: 03/07/2014, 08:20