使用oracle生成xml

时间:2016-11-30 10:33:49

标签: xml oracle plsql

我有跟随我想用oracle生成的xml。

<Component ID="600564" asmid="1" def="FactSheet" type="Document">
    <Profile>
        <Port_ID>182</Port_ID>
        <Inception_Date>31 Dec 1998</Inception_Date>
    </Profile>
    <AverageAnnualReturns>
        <TableData>
            <Item>
                <ClassID>33</ClassID>
                <ClassName>A1USD</ClassName>
                <Superscript>2</Superscript>
                <Superscript_TCE/>              
            </Item>
            <Item>
                <ClassID>45</ClassID>
                <ClassName>I1EUR</ClassName>
                <Superscript>1,2</Superscript>
                <Superscript_TCE/>              
            </Item>
        </TableData>
        <SuppressLifeColumn>Yes</SuppressLifeColumn>
        <SuppressBenchColumn10yr>No</SuppressBenchColumn10yr>
        <SuppressBenchColumn5yr>No</SuppressBenchColumn5yr>
        <SuppressBenchColumn3yr>No</SuppressBenchColumn3yr>
        <SuppressBenchColumn1yr>No</SuppressBenchColumn1yr>
    </AverageAnnualReturns>
</Component>

查询个人资料如下

SELECT PCR.PORT_ID,  
to_char(p.port_start_dt, 'dd Mon yyyy') as INCEPTION_DATE 
FROM edp_admin.PORT_CLASS_REPORT PCR 
JOIN edp_admin.PORTFOLIO p on (PCR.PORT_ID = P.PORT_ID and PCR.CLASS_ID = P.BASE_CLASS_ID) 
where PCR.PORT_ID = 182 AND PCR.REPORT_ID = 472

查询AverageAnnualReturn如下

SELECT distinct MPR.PORT_ID, 
MPR.CLASS_ID, 
MPR.CLASS_NAME, 
PCR.VALUE_NUM3 as RANK, 
NVL (NC.SUPERSCRIPT_TEXT,' ') as SUPERSCRIPT_TEXT 
FROM EDP_ADMIN.SYSTEM_VALUE PCR 
LEFT JOIN EDP_ADMIN.MPR_MIL_VIEW MPR ON (PCR.VALUE_NUM1 = MPR.PORT_ID AND PCR.VALUE_NUM2 = MPR.CLASS_ID AND MPR.CLASSIF_ID = 206) 
LEFT JOIN EDP_ADMIN.PORT_CLASS_YIELD PCY ON (PCR.VALUE_NUM1 = PCY.PORT_ID AND PCR.VALUE_NUM2 = PCY.CLASS_ID AND MPR.PROFILE_DATE = PCY.PORT_CLASS_YIELD_DT AND PCY.YIELD_ID = 6) 
LEFT JOIN EDP_ADMIN.PORTFOLIO_CLASS PC ON (PCR.VALUE_NUM1 = PC.PORT_ID AND PCR.VALUE_NUM2 = PC.CLASS_ID) 
LEFT JOIN EDP_ADMIN.PORT_CLASS_MKT_PRICE PCMP ON (PCR.VALUE_NUM1 = PCMP.PORT_ID AND PCR.VALUE_NUM2 = PCMP.CLASS_ID AND PCMP.MKT_PRICE_ID = 12 AND MPR.PROFILE_DATE = PCMP.PORT_CLA_MKT_PRICE_PER_END_DT) 
LEFT JOIN (SELECT DISTINCT R1.PORT_ID, R1.CLASS_ID, R1.PORT_CLASS_EXP_RAT_VALUE, R1.PORT_CLASS_EXP_RAT_DT FROM edp_admin.Port_Class_Expense_Ratio R1 INNER JOIN (SELECT DISTINCT PORT_ID, CLASS_ID, MAX(PORT_CLASS_EXP_RAT_DT) as MONTH_END_DATE FROM EDP_ADMIN.PORT_CLASS_EXPENSE_RATIO GROUP BY PORT_ID, CLASS_ID ) R2 ON (R1.PORT_ID = R2.PORT_ID AND R1.CLASS_ID = R2.CLASS_ID AND R1.PORT_CLASS_EXP_RAT_DT = R2.MONTH_END_DATE) ) PCER ON PCR.VALUE_NUM1 = PCER.PORT_ID and PCR.VALUE_NUM2 = PCER.CLASS_ID 
LEFT JOIN EDP_ADMIN.FN_MIL_FS_CONCAT_NOTES_VIEW NC ON NC.PORT_ID = PCR.VALUE_NUM1 AND NC.CLASS_ID = PCR.VALUE_NUM2 AND NC.HYPO_TYPE = PCR.VALUE_CHAR1 
WHERE PCR.CODE = 'MIL_FS_PERF_CONFIG' AND PCR.VALUE_NUM1 IN (182) AND PCR.VALUE_CHAR1 = 'UK' ORDER BY RANK

我尝试使用oracle sql函数生成xml,如下所示

select dbms_xmlquery.getxml(sql for profile) from dual

但它会生成两个额外的xml节点rowset和row,如下所示

<?xml version = '1.0'?>
<ROWSET>
   <ROW num="1">
      <PORT_ID>182</PORT_ID>
      <INCEPTION_DATE>31 Dec 1998</INCEPTION_DATE>      
   </ROW>
</ROWSET>

其他方式是

select xmlelement("Component",xmlattributes('600564' as ID,
                                             '1' as asmid,
                                             'FactSheet' as def,
                                             'Document' as type
                                             ),
                  xmlagg(
                  xmlelement("Profile")

                  )                                            

            )from dual

它生成如下结构

<Component ID="600564" ASMID="1" DEF="FactSheet" TYPE="Document"><Profile></Profile></Component>

BUt我不打算如何在profile节点下填充数据,然后averageannualreturns

1 个答案:

答案 0 :(得分:2)

您可以使用子选择来获取profileaverageannualreturns节点的数据。例如:

select xmlelement("Component",
         xmlattributes('600564' as ID,
                       '1' as asmid,
                       'FactSheet' as def,
                       'Document' as type
         ),
        (
         SELECT XMLELEMENT("Profile",
                  XMLFOREST(
                    'example_port' AS "Port_ID",  
                    '30/11/2016' as "Inception_Date" 
                  )
                )
         FROM dual
        )                                 
) from dual;

我相信这是你需要的东西(尽管我没有你要测试的桌子):

select xmlelement("Component",
         xmlattributes('600564' as ID,
                       '1' as asmid,
                       'FactSheet' as def,
                       'Document' as type
         ),
        (
         SELECT XMLELEMENT("Profile",
                  XMLFOREST(
                    PCR.PORT_ID AS "Port_ID",  
                    to_char(p.port_start_dt, 'dd Mon yyyy') as "Inception_Date" 
                  )
                )
         FROM edp_admin.PORT_CLASS_REPORT PCR 
         JOIN edp_admin.PORTFOLIO p on (PCR.PORT_ID = P.PORT_ID and PCR.CLASS_ID = P.BASE_CLASS_ID) 
         where PCR.PORT_ID = 182 AND PCR.REPORT_ID = 472
        ),
        (
          SELECT XMLELEMENT("AverageAnnualReturns",
                   XMLELEMENT("TableData",
                     XMLAGG(
                       XMLELEMENT("Item",
                         XMLFOREST(
                           MPR.CLASS_ID AS "ClassID",
                           MPR.CLASS_NAME AS "ClassName",
                           NVL (NC.SUPERSCRIPT_TEXT,' ') AS "SuperScript",
                           NULL AS "SuperScript_TCE"
                         )
                       )
                     )
                   ),
                   XMLFOREST(
                     'Yes' AS "SupressLifeColumn",
                     'No' AS "SupressBenchColumn10yr",
                     'No' AS "SupressBenchColumn5yr",
                     'No' AS "SupressBenchColumn3yr",
                     'No' AS "SupressBenchColumn1yr"
                   )
                 )
          FROM EDP_ADMIN.SYSTEM_VALUE PCR 
          LEFT JOIN EDP_ADMIN.MPR_MIL_VIEW MPR ON (PCR.VALUE_NUM1 = MPR.PORT_ID AND PCR.VALUE_NUM2 = MPR.CLASS_ID AND MPR.CLASSIF_ID = 206) 
          LEFT JOIN EDP_ADMIN.PORT_CLASS_YIELD PCY ON (PCR.VALUE_NUM1 = PCY.PORT_ID AND PCR.VALUE_NUM2 = PCY.CLASS_ID AND MPR.PROFILE_DATE = PCY.PORT_CLASS_YIELD_DT AND PCY.YIELD_ID = 6) 
          LEFT JOIN EDP_ADMIN.PORTFOLIO_CLASS PC ON (PCR.VALUE_NUM1 = PC.PORT_ID AND PCR.VALUE_NUM2 = PC.CLASS_ID) 
          LEFT JOIN EDP_ADMIN.PORT_CLASS_MKT_PRICE PCMP ON (PCR.VALUE_NUM1 = PCMP.PORT_ID AND PCR.VALUE_NUM2 = PCMP.CLASS_ID AND PCMP.MKT_PRICE_ID = 12 AND MPR.PROFILE_DATE = PCMP.PORT_CLA_MKT_PRICE_PER_END_DT) 
          LEFT JOIN (SELECT DISTINCT R1.PORT_ID, R1.CLASS_ID, R1.PORT_CLASS_EXP_RAT_VALUE, R1.PORT_CLASS_EXP_RAT_DT FROM edp_admin.Port_Class_Expense_Ratio R1 INNER JOIN (SELECT DISTINCT PORT_ID, CLASS_ID, MAX(PORT_CLASS_EXP_RAT_DT) as MONTH_END_DATE FROM EDP_ADMIN.PORT_CLASS_EXPENSE_RATIO GROUP BY PORT_ID, CLASS_ID ) R2 ON (R1.PORT_ID = R2.PORT_ID AND R1.CLASS_ID = R2.CLASS_ID AND R1.PORT_CLASS_EXP_RAT_DT = R2.MONTH_END_DATE) ) PCER ON PCR.VALUE_NUM1 = PCER.PORT_ID and PCR.VALUE_NUM2 = PCER.CLASS_ID 
          LEFT JOIN EDP_ADMIN.FN_MIL_FS_CONCAT_NOTES_VIEW NC ON NC.PORT_ID = PCR.VALUE_NUM1 AND NC.CLASS_ID = PCR.VALUE_NUM2 AND NC.HYPO_TYPE = PCR.VALUE_CHAR1 
          WHERE PCR.CODE = 'MIL_FS_PERF_CONFIG' AND PCR.VALUE_NUM1 IN (182) AND PCR.VALUE_CHAR1 = 'UK' ORDER BY RANK   
        )                                   
) from dual;

使用appendChildXML和plsql的解决方案:

DECLARE
  lComponentXML xmltype;
  lProfileXML   xmltype;
BEGIN
  --generate the component xml
  select xmlelement("Component",
           xmlattributes('600564' as ID,
                         '1' as asmid,
                         'FactSheet' as def,
                         'Document' as type
           )
         )
  INTO lComponentXML
  FROM dual;

  --generate the profile xml
  SELECT XMLELEMENT("Profile",
           XMLFOREST(
             PCR.PORT_ID AS "Port_ID",  
             to_char(p.port_start_dt, 'dd Mon yyyy') as "Inception_Date"
           )
         )
  INTO lProfileXML
  FROM edp_admin.PORT_CLASS_REPORT PCR 
  JOIN edp_admin.PORTFOLIO p on (PCR.PORT_ID = P.PORT_ID and PCR.CLASS_ID = P.BASE_CLASS_ID) 
  where PCR.PORT_ID = 182 AND PCR.REPORT_ID = 472;

  --append the profile xml to the component
  lComponentXML := lComponentXML.appendChildXML('//Component',lProfileXML);
END;