使用XML和XSLT生成SQL

时间:2008-11-25 22:44:47

标签: xml xslt

我有一个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元素,但是删除了所有元素和属性信息,只留下每个元素和属性信息。我认为这可能与输出类型有关。

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

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

我相信Oracle(某些)和SQL Server(如此)都有机制以更加XML友好的方式对包含XML的列进行查询(例如,使用XPath)。

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

答案 1 :(得分:1)

对于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具有属性,则会写出属性值。我找不到一种方法来写出属性,当它们出现时;重新遇到......

有什么想法吗?

答案 2 :(得分:-1)

以下是如何做到的:

<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有点奇怪。