2013-03-26 11 views
0

首先,我的表是這樣的..順序Concatinating XML數據,然後使用XPath脫身數據

Checkpoint_Data 
--------------- 
Checkpoint_Id 
Sequence_Number 
Checkpoint_Data 

Checkpoint 
---------- 
Checkpoint_Id 
Location 
Transaction_Id 

Transaction 
----------- 
Transaction_Id 
Name 
Time 

Checkpoint_data含有分解XML和序列號決定了它是如何組合在一起

我想將所有檢查點鏈接的Checkpoint_Data連接在一起(1,2,...),然後使用XPath來提取我想要的一些數據。

下面是該查詢我現在所擁有的,但它不會做任何拼接,而不能正常工作:

SELECT distinct(xmltype(data.trans_data).extract('//somePath/text()').getStringVal()) 
FROM Checkpoint_Data cpd, Checkpoint cp, Transaction tr 
WHERE cpd.checkpoint_id = cp.checkpoint_id 
    and cp.location = 'someLocation' 
    and cp.trans_id = tr.trans_id 
    and tr.time >= to_date('3/26/2013:8:00 AM', 'mm/dd/yyyy:hh:miam') 
    and tr.time <= to_date('3/26/2013:11:00 AM', 'mm/dd/yyyy:hh:miam') 

我如何可以連接包含在Checkpoint_Data破碎了XML,然後使用XPath從中提取數據?

+0

請問'Checkpoint_Data'列包含每行有效的XML?或它是否像seq 1 =' asdfoo'seq 2 =' asd'等等只有一個有效的XML文檔時連接? – DazzaL 2013-03-26 16:14:44

+0

這是後者。它只是在將所有連接在一起的有效XML – user906153 2013-03-26 17:06:18

回答

1

PLSQL方法:

SQL> create or replace function get_xml_doc(p_id Checkpoint_Data.checkpoint_id%type) 
    2 return xmltype deterministic 
    3 is 
    4 v_xml clob; 
    5 begin 
    6 for r_row in (select cd.checkpoint_data 
    7     from Checkpoint_Data cd 
    8     where cd.checkpoint_id = p_id 
    9     order by cd.sequence_number) 
10 loop 
11  v_xml := v_xml || r_row.checkpoint_data; 
12 end loop; 
13 
14 return xmltype(v_xml); 
15 end get_xml_doc; 
16/

Function created. 

SQL> 
SQL> select cp.checkpoint_id, get_xml_doc(cp.checkpoint_id) xml_doc 
    2 from checkpoint cp, transaction tr 
    3 where cp.location = 'someLocation' 
    4  and cp.trans_id = tr.trans_id 
    5  and tr.time <= sysdate 
    6 group by cp.checkpoint_id; 

CHECKPOINT_ID XML_DOC 
------------- ---------------------------------------- 
      1 <root> 
       <a>1st node</a> 
       <b>2nd node</b> 
       <compType> 
        <a>foo</a> 
       </compType> 
       <d>another node</d> 
       </root> 

或只是SQL如果PLSQL是不是一種選擇:

可以使用CDATAXMLAGG例如:

SQL> select * from Checkpoint_Data; 

CHECKPOINT_ID SEQUENCE_NUMBER CHECKPOINT_DATA 
------------- --------------- -------------------------------------------------- 
      1    1 <root><a>1st node</a><b>2nd node</b> 
      1    2 <compType><a>foo</a></compType><d>another node</d> 
      1    3 </root> 


SQL> select c.xmlstr.transform(xmltype('<xsl:stylesheet version="1.0" 
    2   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    3   <xsl:output method="xml" omit-xml-declaration = "yes" version="1.0" /> 
    4   <xsl:template match="/"> 
    5    <xsl:for-each select="/root/nde"> 
    6     <xsl:sort select="@seq"/> 
    7     <xsl:value-of select="." disable-output-escaping="yes" /> 
    8    </xsl:for-each> 
    9   </xsl:template> 
10  </xsl:stylesheet>')) xml 
11 from (SELECT cpd.checkpoint_id,xmlelement("root", xmlagg(
12     xmltype('<nde seq="' || cpd.sequence_number || '"><![CDATA['||cpd.checkpoint_data||']]></nde>'))) xmlstr 
13   FROM Checkpoint_Data cpd, Checkpoint cp, Transaction tr 
14   WHERE cpd.checkpoint_id = cp.checkpoint_id 
15    and cp.location = 'someLocation' 
16    and cp.trans_id = tr.trans_id 
17    and tr.time <= sysdate 
18   group by cpd.checkpoint_id) c; 

XML 
-------------------------------------------------------------------------------- 
<root><a>1st node</a><b>2nd node</b><compType><a>foo</a></compType><d>another no 
de</d></root> 

,所以我把每個XML片段並將其轉換爲CDATA節點,如:

<node seq="1"><!CDATA[<root><a>1st node</a><b>2nd node</b>]]></node> 

然後用XMLAGG讓這些到一個文檔像

<root> 
    <node seq="1"><!CDATA[<root><a>1st node</a><b>2nd node</b>]]></node> 
    <node seq="3"><!CDATA[</root>]]></node> 
    <node seq="2"><!CDATA[<compType><a>foo</a></compType><d>another node</d>]]></node> 
</root> 

注:該序列可以通過組by..so我申請一個XSL命令他們,並打印出來(你可以寫你自己來jumbed如果你想要的話,可以按照順序彙總,或者只是編寫一個pl/sql例程來獲取所有的片段,然後按照順序添加它們,如果這是一個選項,那麼你可能更喜歡)。

注意:在10g oracle似乎忽略禁用輸出轉義(它在11g中的確定)。如果您使用10g,則可以添加對dbms_xmlgen.convert(clob, 1)的調用來對其進行解碼。

select dbms_xmlgen.convert(
     xmlserialize(
      content c.xmlstr.transform(xmltype('<?xml version="1.0" encoding="ISO-8859-1"?> 
    <xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
     <xsl:output method="xml" version="1.0" omit-xml-declaration = "yes" encoding="UTF-8" indent="no"/> 
     <xsl:template match="/"> 
      <xsl:for-each select="/root/node"> 
       <xsl:sort select="@seq"/> 
       <xsl:value-of select="." disable-output-escaping="yes"/> 
      </xsl:for-each> 
     </xsl:template> 
    </xsl:stylesheet>')) as clob), 1) xsl, xmlstr 
    from (SELECT cpd.checkpoint_id,xmlelement("root", xmlagg(
       xmltype('<node seq="' || cpd.sequence_number || '"><![CDATA['||cpd.checkpoint_data||']]></node>'))) xmlstr 
     FROM Checkpoint_Data cpd, Checkpoint cp, Transaction tr 
     WHERE cpd.checkpoint_id = cp.checkpoint_id 
      and cp.location = 'someLocation' 
      and cp.trans_id = tr.trans_id 
      and tr.time <= sysdate 
     group by cpd.checkpoint_id) c; 

小提琴:http://sqlfiddle.com/#!4/e1bf8/1

+0

select語句很好用,但是如何使用XPath從某個XML節點獲取所需數據,例如?我想從中得到你選擇語句返回的所有XML的數據 – user906153 2013-03-26 18:31:14

+0

@ user906153你可以在返回的XML文檔上使用'extractvalue'來做到這一點。 – DazzaL 2013-03-26 21:02:43

+0

@ user906153例如參見小提琴http://sqlfiddle.com/#!4/e1bf8/3第二條語句。 – DazzaL 2013-03-26 21:08:26

相關問題