2013-03-18 50 views
1

我正在試驗Python和Oracle XML DB。我在Oracle 11g數據庫中有一個包含XMLType列和ID列的表。 XML列的存儲模型是對象關係。有時候,我需要得到一個整體的XML文件,而往往是超過4000個字符長,所以我用這個查詢得到一個CLOB:從Oracle數據庫讀取的XML文件中的額外空白 - 爲什麼?

select t.representation.getclobval() 
from myxmldocs t 
where id=:documentId 

當我運行此查詢的輸出包括多餘的空格,用換行和在我插入的XML文檔中絕對不存在的XML元素之間的選項卡。效果是某種格式,使輸出看起來像這樣:

<A>\n 
\t<B></B>\n 
\t\t<C>Some text</C>\n 
\t\t<C>Some more text</C>\n 
\t<B></B>\n 
... 

等等。非常漂亮和可讀,但爲什麼我會得到它?它還會混淆我正在使用的其他庫,這會扼殺額外的空格。

如果我刪除getclobval()我的Python客戶端沒有得到一個CLOB,但一個對象,我不知道如何處理它。

這似乎一致;我使用sqlplus命令行客戶端來解決這個問題,並使用不同的XML Schema創建其他表,然後查詢它們。在我原型的以前版本中,我使用XMLType列使用CLOB存儲模型,但沒有這個問題。

我應該如何重寫查詢以僅使用XML文件獲取CLOB而沒有額外的格式?


更新:

:按照意見要求,這是我得到運行命令行客戶端查詢 select dump(t.representation) from myxmldocs t where id=:documentId輸出(:從數據庫的實際,現有的ID documentId更換當然)
DUMP(T.REPRESENTATION) 
-------------------------------------------------------------------------------- 
Typ=58 Len=218: 32,156,148,1,0,0,0,0,80,193,223,20,0,0,0,0,216,15,47,21,0,0,0,0, 
80,44,55,21,0,0,0,0,0,202,154,59,160,15,0,0,160,15,0,0,1,0,4,0,220,190,195,71,1, 
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,174,33,65,0,15,0,72,0,1,0,0,0,0,0,0,0,49,0 
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 
,0,0,0,0,0,0,0,0 
+1

「它還會混淆我正在使用的其他圖書館對額外空白區域的遏制。「 - 那些圖書館很差。這些空格是完全合法的XML。 – Mat 2013-03-18 10:45:44

+0

同意,但我沒有控制庫,它提供了一個功能,從零開始重新實現真的非常耗時。 – Btz 2013-03-18 11:01:58

+1

@Btz,你可以用查詢結果更新你的問題:'從myxmldocs中選擇dump(t.representation)t其中id =:documentId'? – 2013-03-18 11:41:47

回答

6
在11g

可以使用xmlserialize

SQL> select t.test.getclobval() from testxml t where id = 1; 

T.TEST.GETCLOBVAL() 
-------------------------------------------------------------------------------- 
<A> 
    <B> 
    <C>foo</C> 
    <C>foo2</C> 
    </B> 
</A> 


SQL> select xmlserialize(document t.test as clob no indent) from testxml t where id = 1; 

XMLSERIALIZE(DOCUMENTT.TESTASCLOBNOINDENT) 
-------------------------------------------------------------------------------- 
<A><B><C>foo</C><C>foo2</C></B></A> 
+0

對於'XMLSERIALIZE' +1,我不知道。你爲什麼說你不應該使用'getClobVal()'?我的印象是這個函數本身執行* no *計算! – 2013-03-18 12:16:25

+2

@VincentMalgrat'getclobval'被'xmlserialize'所取代。注意1407946.1(xml數據庫性能指南)指出:「由於XDB優化了XMLSerialize,所以推薦使用XMLSerialize,因此執行得更好,而不是使用getclobval()。此外,從11.2.x開始xmltype.getclobval函數已被棄用。是的,它不會重新格式化XML,但在對象關係的情況下,默認情況下,xml始終會打印出來,所以我們需要使用「無縮進」來撤消它(或者您已經用strip + noindent顯示了XSL在10g和更早)。 – DazzaL 2013-03-18 12:20:47

+0

非常有趣,我想我會去XMLSERIALIZE。然而,我也設法得到這個工作:'選擇to_clob(xmlquery('./ node()'傳遞t.representation返回內容))從myxmldocs t其中id = 1'。也許這對於那些使用10g的人來說是有效的,以避免必須用XSLT重新格式化XML?在這種情況下使用to_clob()有什麼缺點?該文檔說:_TO_CLOB將LOB列或其他字符串中的NCLOB值轉換爲CLOB值._我不知道這是否會使非ASCII字符的文檔(如中文)變得困難? – Btz 2013-03-18 12:44:00

0

getClobVal()方法不應該修改數據的縮進。您的XML可能在插入過程中或之前被格式化。

可以transform進XML刪除空格:(其實你不應該使用getclobval了它不建議性能的原因)

SQL> SELECT XMLTYPE.createxml(
    2 '<a> 
    3  <b><c></c></b> 
    4 </a>' 
    5 ).transform(XMLTYPE(
    6 '<?xml version="1.0"?> 
    7 <xsl:stylesheet version="1.0" 
    8  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > 
    9  <xsl:output method="xml" indent="no"/> 
10  <xsl:strip-space elements="*"/> 
11  <xsl:template match="@*|node()"> 
12  <xsl:copy> 
13  <xsl:apply-templates select="@*|node()"/> 
14  </xsl:copy> 
15 </xsl:template> 
16 </xsl:stylesheet> 
17 ')).getClobVal() FROM dual; 

<?xml version="1.0" encoding="utf-8"?> 
<a><b><c></c></b></a>