I stick my finger into existence and it smells of nothing. Where am I? What is this called the world? Who is it that lured me here? How did I come into this world? Why was I not consulted? Oh I stick my finger into existence and it smells of nothing.
- Søren Kierkegaard
PostgreSQL XML
Table of Contents
PostgreSQL XML Support
As of version 8.3 (not yet in Beta as of this writing), PostgreSQL supports a native XML data type and implements SQL/XML 2003. This data type is capable of storing well formed documents and content fragments. SQL/XML, an alternative to XQuery, is specifically designed for working with XML in relational databases.
Creating Basic XML Documents
Create a document from plain XML text:
example=# SELECT XMLPARSE (DOCUMENT '<?xml version="1.0" encoding="UTF-8"?>
example'# <root>
example'#     <parent name="p1">
example'#         <child name="c1">Child One</child>
example'#         <child name="c2">Child Two</child>
example'#         <child name="c3" />
example'#     </parent>
example'#     <parent name="p2" />
example'# </root>');
                  xmlparse                  
--------------------------------------------
 <root>
     <parent name="p1">
         <child name="c1">Child One</child>
         <child name="c2">Child Two</child>
         <child name="c3" />
     </parent>
     <parent name="p2" />
 </root>
(1 row)
		
Or typecast the text to XML:
example=# SELECT xml '<root>
example'#     <parent name="p1">
example'#         <child name="c1">Child One</child>
example'#         <child name="c2">Child Two</child>
example'#         <child name="c3" />
example'#     </parent>
example'#     <parent name="p2" />
example'# </root>'::xml;
                    xml                     
--------------------------------------------
 <root>
     <parent name="p1">
         <child name="c1">Child One</child>
         <child name="c2">Child Two</child>
         <child name="c3" />
     </parent>
     <parent name="p2" />
 </root>
(1 row)
		
Take an XML document and convert it to a genuine character string:
example=# SELECT XMLSERIALIZE(DOCUMENT '<?xml version="1.0" encoding="UTF-8"?>
example'# <root>
example'#     <parent name="p1">
example'#         <child name="c1">Child One</child>
example'#         <child name="c2">Child Two</child>
example'#         <child name="c3" />
example'#     </parent>
example'#     <parent name="p2" />
example'# </root>'::xml AS text);
                xmlserialize                
--------------------------------------------
 <?xml version="1.0" encoding="UTF-8"?>
 <root>
     <parent name="p1">
         <child name="c1">Child One</child>
         <child name="c2">Child Two</child>
         <child name="c3" />
     </parent>
     <parent name="p2" />
 </root>
(1 row)
		
A more likely real-world use would be on a table with a column with the xml data type:
example=# SELECT XMLSERIALIZE(DOCUMENT doc_content AS text) from test;
                xmlserialize                
--------------------------------------------
 <?xml version="1.0" encoding="UTF-8"?>
 <root>
     <parent name="p1">
         <child name="c1">Child One</child>
         <child name="c2">Child Two</child>
         <child name="c3" />
     </parent>
     <parent name="p2" />
 </root>
(1 row)
		
SQL/XML Publishing Functions
PostgreSQL's XML functionality extends to more than just basic documents and content. The basics of SQL/XML 2003 are implemented to help make working with XML data much easier.
XMLCOMMENT
XMLCOMMENT can be used to create a comment:
example=# SELECT XMLCOMMENT('  This is a comment  ');
          xmlcomment          
------------------------------
 <!--  This is a comment  -->
(1 row)
			
Perhaps a more likely real-world example:
example=# SELECT XMLCOMMENT('This comes from the ' || doc_name || ' document')
example-# FROM test;
                  xmlcomment                   
-----------------------------------------------
 <!--This comes from the test1.xml document-->
(1 row)
			
XMLCONCAT
XMLCONCAT can take an arbitrary series of XML content and piece them together for a single result:
example=# SELECT XMLCONCAT(   XMLCOMMENT('begin chapter one'), '
example'# <chapter number="1" />
example'# ', XMLCOMMENT('begin chapter two'), '
example'# <chapter number="2" />
example'# ', XMLCOMMENT('begin chapter three'), '
example'# <chapter number="3" />');
         xmlconcat          
----------------------------
 <!--begin chapter one-->
 <chapter number="1" />
 <!--begin chapter two-->
 <chapter number="2" />
 <!--begin chapter three-->
 <chapter number="3" />
(1 row)
			
Combining XML documents with declarations:
example=# SELECT XMLCONCAT('<?xml version="1.1" encoding="UTF-8"?>
example'# <chapter number="1" />
example'# ', '<?xml version="1.1" encoding="UTF-8"?><chapter number="2" />
example'# ', '<?xml version="1.1" encoding="UTF-8"?><chapter number="3" />');
       xmlconcat        
------------------------
 <?xml version="1.1"?>
 <chapter number="1" />
 <chapter number="2" />
 <chapter number="3" />
(1 row)
			
Note that conflicting declaration attributes get discarded. The same statement with <?xml version="1.0"?> will get the entire declaration discarded always.
XMLELEMENT
XMLELEMENT is used to construct individual elements. It takes a name, a series of attributes, and then the content of the element. It can use other statements or expressions to help build the pieces of the XML Element:
example=# SELECT  XMLELEMENT(name chapter,
example(#             XMLATTRIBUTES(
example(#                 '1' AS number, 
example(#                 CURRENT_DATE as current_date,
example(#                 (SELECT doc_name FROM test) AS doc_name), 
example(#             'The content of chapter one');
                                               xmlelement                                                
---------------------------------------------------------------------------------------------------------
 <chapter number="1" current_date="2007-09-20" doc_name="test1.xml">The content of chapter one</chapter>
(1 row)
			
XMLFOREST
XMLFOREST is used to create an arbitrary series of XML nodes. The result is not well formed XML, but it can be used for further processing or for inclusion within a larger document.
example=# SELECT  XMLFOREST(table_name, column_name)
example-# FROM    information_schema.columns
example-# WHERE   table_schema = 'public';
                              xmlforest                              
---------------------------------------------------------------------
 <table_name>test</table_name><column_name>doc_name</column_name>
 <table_name>test</table_name><column_name>doc_content</column_name>
(2 rows)
			
XMLPI
XMLPI is used for creating XML Processing Instructions. These are useful for further document processing (via XSL, for example).
example=# SELECT XMLPI(name php, 'echo "hello world";');
            xmlpi            
-----------------------------
 <?php echo "hello world";?>
(1 row)
			
A more complex example:
example=# SELECT  XMLELEMENT(
example(#             name chapter, 
example(#             XMLATTRIBUTES('1' AS number), 
example(#             'Chapter One Content',
example(#             XMLPI(name mycustompi, ' doc="' || (SELECT doc_name FROM test) || '"'));
                                   xmlelement                                    
---------------------------------------------------------------------------------
 <chapter number="1">Chapter One Content<?mycustompi doc="test1.xml"?></chapter>
(1 row)
			
Memory allocated: 262,144 bytes
Page run time: 0.0187 seconds