【问题标题】:Extra whitespace in XML file read from Oracle database - why?从 Oracle 数据库读取的 XML 文件中的额外空格 - 为什么?
【发布时间】:2013-03-18 10:43:27
【问题描述】:

我正在试验 Python 和 Oracle XML DB。我在 Oracle 11g 数据库中有一个包含 XMLType 列和 ID 列的表。 XML 列的存储模型是对象关系的。有时我需要获取整个 XML 文件,而且通常超过 4000 个字符,因此我使用此查询来获取 CLOB:

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 模式创建了其他表,然后查询它们。在我的原型的早期版本中,我的 XMLType 列使用了 CLOB 存储模型并且没有这个问题。

我应该如何重写查询以获取带有 XML 文件的 CLOB,而不需要额外的格式?


更新:根据 cmets 的要求,这是我从命令行客户端运行查询 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

【问题讨论】:

  • “它还会弄乱我正在使用的其他库,因为它会扼杀额外的空白。” - 那些图书馆很差。这些空格是完全合法的 XML。
  • 同意,但我无法控制该库,它提供的功能从头开始重新实现非常非常耗时。
  • @Btz,你能用查询结果更新你的问题吗:select dump(t.representation) from myxmldocs t where id=:documentId
  • 刚刚用您的查询输出更新了问题,@A.B.Cade。

标签: xml oracle xmltype


【解决方案1】:

在 11g 中你可以使用xmlserialize(事实上你不应该再使用getclobval了。出于性能原因不推荐使用)

 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>

【讨论】:

  • +1 for XMLSERIALIZE,我不知道。为什么你说你不应该使用getClobVal()?我的印象是这个函数自己执行no计算!
  • @VincentMalgrat getclobvalxmlserialize 取代。注意 1407946.1(xml db 的性能指南)状态 It is recommended to XMLSerialize since its optimized by the XDB and thus performs better rather than using getclobval(). In addition from 11.2.x onwards xmltype.getclobval function is deprecated anyway.。是的,它不会重新格式化 XML,但是在对象关系的情况下,默认情况下 xml 总是会打印得很漂亮,所以我们需要用“no indent”撤消这个(或者你已经展示了一个带有 strip + noindent 的 XSL 10g 及更早版本)。
  • 非常有趣,我想我会选择 XMLSERIALIZE。但是,我也设法让它工作:select to_clob(xmlquery('./node()' passing t.representation returning content)) from myxmldocs t where id=1。也许这对那些使用 10g 的人有用,以避免必须用 XSLT 重新格式化 XML?在这种情况下使用 to_clob() 有什么缺点?文档说:TO_CLOB 将 LOB 列或其他字符串中的 NCLOB 值转换为 CLOB 值。我想知道这是否会使具有非 ASCII 字符(例如中文)的文档变得困难?
  • @Btz 我不会在 10g 中使用 to_clob() 而不是 getclobval()(即使在 10g 上,我仍然会在 xquery 版本中使用 xmlserialize。它会工作得很好)。
【解决方案2】:

getClobVal() 方法不应修改数据的缩进。您的 XML 可能在插入期间或之前已被格式化。

您可以transform XMLType 来删除空格:

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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-17
    • 2021-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多