【问题标题】:Generating SQL using XML and XSLT使用 XML 和 XSLT 生成 SQL
【发布时间】:2010-09-24 01:35:19
【问题描述】:

我有一个 XML 定义,其中包含一个带有子元素的元素。例如:

<a>
 <b>
  <c>C</c>
  <d>D</d>
 </b>
</a>

我有一个带有文本输出的 XSLT。例如:

<xsl...>
  <xsl:output method="text" indent="yes"/>
  <xsl:template match="/">
    <xsl:copy-of select="/a/b" />
  ...

我想将整个 b 元素及其子元素复制到一个已删除空格的字符串中,以便生成 SQL 查询。例如:

select * from some-table where xml = '<b><c>C</c><d>D</d></b>'

目前,copy-of 正在查找 b 元素,但丢弃所有元素和属性信息,只留下每个元素中的文本内容。我认为这可能与输出类型有关。

有什么想法吗?

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    你的 SQL 语句让我害怕。 XML 区分大小写,如果输入的 XML 和 XSLT(包括所有元素、属性和值)的大小写与原始数据库插入中使用的不完全相同,那么您的比较可能会失败。

    我相信 Oracle(确定)和 SQL Server(认为是这样)都具有以更 XML 友好的方式(例如,使用 XPath)对包含 XML 的列进行查询的机制。

    你到底想做什么?您的问题似乎比让这个 XSLT 正确转换更深。

    【讨论】:

    • 问题的重点不是xml的内容,也不是查询的内容,而是将xml复制为纯文本。
    • SQL Server 2000(目标数据库)确实支持 XML 生成,但会调用 MSXML 解析器。在幕后,这会消耗 SQL Server 使用的内存(我被告知大约有三分之一)。这是不可取的,因为这最终会出现在性能关键系统中。
    • 体面的内置 xml 支持最早出现在 SQL Server 2005 中
    【解决方案2】:

    对于 XSLT 来说,这项任务可能有点太具有挑战性了。我能得到的最接近的是:

      <xsl:template match="b//*|node()">
        <xsl:copy>
          <xsl:text>&lt;</xsl:text>
          <xsl:value-of select="name()"/>
          <xsl:text>&gt;</xsl:text>
          <xsl:value-of select="text()"/>
          <xsl:apply-templates select="*"/>
          <xsl:text>&lt;/</xsl:text>
          <xsl:value-of select="name()"/>
          <xsl:text>&gt;</xsl:text>
        </xsl:copy>
      </xsl:template>
    

    并且被调用:

      <xsl:apply-templates select="/a/b/self::*"/>
    

    这会产生以下内容:

     <b>
      <c>C</c>
      <d>D</d>
     </b>
    

    我的“解决方案”失败的地方是元素具有属性时。如果 b 有一个属性,则该属性值被写出。我找不到在遇到属性时写出属性的方法……

    有什么想法吗?

    【讨论】:

      【解决方案3】:

      这是如何做到的:

      <xsl:output method="xml" />
      
      <xsl:template match="/"><xsl:apply-templates select="/a/b" mode="normalize-space" /></xsl:template>
      
      <xsl:template match="text()" mode="normalize-space"><xsl:value-of select="normalize-space(.)" /></xsl:template>
      <xsl:template match="@*|node()" mode="normalize-space"><xsl:copy><xsl:apply-templates select="@*|node()" mode="normalize-space" /></xsl:copy></xsl:template>
      

      此方法复制节点,节点具有命名空间和属性。

      方法要求输出为“xml”(而不是原始示例中的“text”)。它为所有 TEXT 节点使用自定义模板来规范它们内部的空间(删除前导/尾随空格,将多个空格压缩为一个空格)。然后,它使用简单的“身份”模板复制所有节点及其属性。两个模板都使用特殊模式以不干扰 XSL 的其余部分。

      不幸的是,XSLT 处理器将 xsl:template 标记内的所有“未知”节点复制到输出文档中,而空格就是这样的节点之一。这就是为什么所有这些模板都需要写在一行中,没有多余的空格。

      PS 虽然,我同意在 RDBMS 中搜索规范化的 XML 有点奇怪。

      【讨论】:

      • 很好的答案,但我需要一些带有文本输出的东西。我添加的一点 XSLT 让我几乎完全了解了那里,但没有很好地处理属性。原来是用SQL输出XML。谢谢。
      猜你喜欢
      • 2021-03-21
      • 1970-01-01
      • 2014-08-17
      • 1970-01-01
      • 1970-01-01
      • 2017-05-09
      • 1970-01-01
      • 2013-08-13
      • 2011-03-24
      相关资源
      最近更新 更多