Build an XML with XMLELEMENT - ORACLE SQL 11g query

白昼怎懂夜的黑 提交于 2019-12-10 12:18:01

问题


I'm trying to create the following XML using a SQL query (Oracle):

 <Changes>
   <Description>Some static test</Description>
   <Notes>Some static test</Notes>

   <UserChange>
      <Operation>Static Text</Operation>
      <User>VALUE from Table - record #1</User>
      <BusinessSource>VALUE from Table #1</BusinessSource>
      <ApplicationRole>VALUE from Table #1</ApplicationRole>
   </UserChange>
    <UserChange>
      <Operation>Static Text</Operation>
      <User>VALUE from Table - record #2</User>
      <BusinessSource>VALUE from Table #2</BusinessSource>
      <ApplicationRole>VALUE from Table #2</ApplicationRole>
   </UserChange>
    <UserChange>
      <Operation>Static Text</Operation>
      <User>VALUE from Table - record #3</User>
      <BusinessSource>VALUE from Table #3</BusinessSource>
      <ApplicationRole>VALUE from Table #3</ApplicationRole>
   </UserChange>   
</Changes>

The table I'm using looks like this:

ID    USER     SOURCE   ROLE
1     test1    src1     role1
2     test1    src1     role1
3     test1    src1     role2
4     user2    src      role
5     user3    src      role
6     user1    src      role

I want to write a query that will create a dynamic XML based on the values in the table. For example: The query should only take the values where user='test1' and the output will be the following XML:

<Changes>
   <Description>Some static test</Description>
   <Notes>Some static test</Notes>

   <UserChange>
      <Operation>Static Text</Operation>
      <User>user1</User>
      <BusinessSource>src1</BusinessSource>
      <ApplicationRole>role1</ApplicationRole>
   </UserChange>
   <UserChange>
      <Operation>Static Text</Operation>
      <User>user1</User>
      <BusinessSource>src1</BusinessSource>
      <ApplicationRole>role1</ApplicationRole>
   </UserChange>
   <UserChange>
      <Operation>Static Text</Operation>
      <User>user1</User>
      <BusinessSource>src1</BusinessSource>
      <ApplicationRole>role2</ApplicationRole>
   </UserChange>   
</Changes>

I've started to write the query:

SELECT XMLElement("Changes", 
              XMLElement("Description", 'sometext'),
              XMLElement("Notes", 'sometext'),
              XMLElement("FulfillmentDate", 'Some Date'),

                  XMLElement("UserChange",
                  XMLElement("Operation", 'sometext'),
                  XMLElement("User", 'sometext'),
                  XMLElement("BusinessSource", 'sometext'),
                  XMLElement("ApplicationRole", 'sometext')                      

                  )).GETSTRINGVAL() RESULTs
               FROM DUAL;

I need to iterate on the other values and make them part of the complete XML.

Appreciate your help.

Thanks


回答1:


I was able to find a solution:

select XMLElement("Changes", 
              XMLElement("Description", 'sometext'),
              XMLElement("Notes", 'sometext'),
              XMLElement("FulfillmentDate", 'Some Date'),
                  XMLAgg(XML_CANDIDATE) ).GETSTRINGVAL() RESULTS

from 
(

select XMLAGG(
        XMLElement("UserChange",
        XMLElement("Operation", 'sometext'),
        XMLElement("User", 'sometext'),
        XMLElement("BusinessSource", 'sometext'),
        XMLElement("ApplicationRole", 'sometext')))  XML_CANDIDATE
from
table);



回答2:


For future readers, here are open source programming solutions to transfer a SQL query to XML document, using OP's data needs as example.

Below code examples are not restricted to any database SQL dialect (i.e., transferrable to other RDBMS using corresponding connection modules as below are Oracle-specific).

For Python (using cx_Oracle and lxml modules):

import os
import cx_Oracle
import lxml.etree as ET

# Set current directory
cd = os.path.dirname(os.path.abspath(__file__))

# DB CONNECTION AND QUERY
db = cx_Oracle.connect("uid/pwd@database")    
cur = db.cursor()
cur.execute("SELECT * FROM OracleData where user='test1'")

# WRITING XML FILE
root = ET.Element('Changes')
DescNode = ET.SubElement(root, "Description").text = 'Some static test'    
NotesNode = ET.SubElement(root, "Notes").text = 'Some static test'  

# LOOPING THROUGH QUERY RESULTS TO WRITE CHILD ELEMENTS 
for row in cur.fetchall():
    UCNode = ET.SubElement(root, "UserChange")
    ET.SubElement(UCNode, "Operation").text = 'Static Text'    
    ET.SubElement(UCNode, "User").text = row[1]
    ET.SubElement(UCNode, "BusinessSource").text = row[2]    
    ET.SubElement(UCNode, "ApplicationRole").text = row[3]   

# CLOSE CURSOR AND DATABASE
cur.close()
db.close()

tree_out = (ET.tostring(root, pretty_print=True, xml_declaration=True, encoding="UTF-8"))

xmlfile = open(os.path.join(cd, 'OracleXML.xml'),'wb')
xmlfile.write(tree_out)
xmlfile.close()

For PHP (using PDO Oracle OCI and DOMDocument)

// Set current directory
$cd = dirname(__FILE__);

// create a dom document with encoding utf8 
$domtree = new DOMDocument('1.0', 'UTF-8');
$domtree->formatOutput = true;
$domtree->preserveWhiteSpace = false;

// Opening db connection
$db_username = "your_username";
$db_password = "your_password";
$db = "oci:dbname=your_sid";

try {
    $dbh = new PDO($db,$db_username,$db_password);          
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $sql = "SELECT * FROM OracleData where user='test1'";    
    $STH = $dbh->query($sql);    
    $STH->setFetchMode(PDO::FETCH_ASSOC); 
}

catch(PDOException $e) {  
    echo $e->getMessage();
    exit;
}

/* create the root element of the xml tree */
$xmlRoot = $domtree->createElement("Changes");
$xmlRoot = $domtree->appendChild($xmlRoot);

$DescNode = $xmlRoot->appendChild($domtree->createElement('Description',  'Some static test'));
$NotesNode = $xmlRoot->appendChild($domtree->createElement('Notes',  'Some static test'));

/* loop query results through child elements */
while($row = $STH->fetch()) {  

    $UCNode = $xmlRoot->appendChild($domtree->createElement('UserChange'));

    $operationNode = $UCNode->appendChild($domtree->createElement('Operation', 'Some static text'));
    $userNode = $UCNode->appendChild($domtree->createElement('User', $row['USER']));
    $sourceNode = $UCNode->appendChild( $domtree->createElement('BusienssSource', $row['SOURCE']));
    $roleNode = $UCNode->appendChild($domtree->createElement('ApplicationRole', $row['ROLE']));

}

file_put_contents($cd. "/OracleXML.xml", $domtree->saveXML());

# Closing db connection
$dbh = null;
exit;

For R (using ROracle and XML packages):

library(XML)
library(ROracle)

# SET CURRENT DIRECTORY   
setwd("C:\\Path\\To\\R\\Script")

# OPEN DATABASE AND QUERY
conn <-dbConnect(drv, username = "", password = "", dbname = "")
df <- dbGetQuery(conn, "select * from OracleData where user= 'test1';")
dbDisconnect(conn)

# CREATE XML FILE
doc = newXMLDoc()
root = newXMLNode("Changes", doc = doc)
descNode = newXMLNode("Description", "Some static test", parent = root)
notesNode = newXMLNode("Notes", "Some static test", parent = root)

# WRITE XML NODES AND DATA
for (i in 1:nrow(df)){
  UCNode = newXMLNode("UserChange", parent = root)

  operationNode = newXMLNode("Operation", "Some static text", parent = UCNode)
  userNode = newXMLNode("User", df$USER[i], parent = UCNode)
  sourceNode = newXMLNode("BusinessSource", df$SOURCE[i], parent = UCNode)
  roleNode = newXMLNode("ApplicationRole", df$ROLE[i], parent = UCNode)
}

# OUTPUT XML CONTENT TO FILE
saveXML(doc, file="OracleXML.xml")



回答3:


You can use this query:

select xmlelement("Changes",
           xmlforest(
               'Some Static Text' "Description"
             , 'Some Static Text' "Notes")
         , xmlagg(
             xmlelement("UserChange",
               xmlforest('Static Text' "Operation",
                         "USER" "User",
                         SOURCE "BusinessSource",
                         ROLE "ApplicationRole")
             )
           )
       ),getclobval()
  from table
 where "USER" = 'test1';

But remember that the XMLAGG function is an aggregate function. In this case every selected column from table is included in the aggregate, so no group by is needed. However, if you wanted to include some column from table outside of the XMLAGG you would need to include them in a group by statement. Also since USER is a reserved word it needs to be surrounded by double quotes to be used as a column reference.



来源:https://stackoverflow.com/questions/32424049/build-an-xml-with-xmlelement-oracle-sql-11g-query

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!