问题
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