使用XMLELEMENT构建XML - ORACLE SQL 11g查询

时间:2015-09-06 13:22:05

标签: sql xml oracle oracle11g

我正在尝试使用SQL查询(Oracle)创建以下XML:

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

我正在使用的表格如下:

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

我想编写一个查询,根据表中的值创建动态XML。 例如: 查询应仅采用user ='test1'的值,输出将是以下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>

我已经开始编写查询:

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;

我需要迭代其他值并使它们成为完整XML的一部分。

感谢您的帮助。

由于

3 个答案:

答案 0 :(得分:0)

我找到了解决方案:

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);

答案 1 :(得分:0)

对于未来的读者,以下是使用OP的数据需求将SQL查询转换为XML文档的开源编程解决方案。

下面的代码示例不限于任何数据库SQL方言(即,使用相应的连接模块可转移到其他RDBMS,如下所示)。

对于Python(使用cx_Oracle和lxml模块):

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()

对于PHP(使用PDO Oracle OCI和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;

对于R(使用ROracle和XML包):

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")

答案 2 :(得分:0)

您可以使用此查询:

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';

但请记住,XMLAGG函数是一个聚合函数。在这种情况下,表中的每个选定列都包含在聚合中,因此不需要group by。但是,如果要在XMLAGG外部的表中包含某些列,则需要将它们包含在group by语句中。此外,由于USER是保留字,因此需要用双引号括起来用作列引用。