我有一个大的xml文档,如下所示:
<?xml version="1.0" encoding="UTF-8" ?>
<Data>
<aTable>
<aTableRow Col1="1" Col2="someText"/>
<aTableRow Col1="2" Col2="newText"/>
...
</aTable>
<anotherTable>
<anotherTableRow Col3="someText" Col4="42"/>
<anotherTableRow Col3="myText" Col4="34"/>
...
</anotherTable>
...
</Data>
我需要在SQL INSERT语句的相应序列中转换文档。类似的东西:
INSERT INTO aTable (Col1, Col2) VALUES (1, "someText")
我已经从&#34;表&#34;到相应的SQL语句,但xslt输出的生成顺序与文档的顺序相同。
有没有办法在aTable之前拥有例如anotherTable?
修改
感谢您的评论和回答。阅读他们我意识到我原来的问题并不清楚。我会尝试添加更多细节。
我已经生成了一个模板,可以正确转换插入语句序列中的xml数据,假设此模板名为&#34; insertGeneration&#34;。
然后我写了类似的东西:<xsl:template match="Data/anotherTable">
<xsl:call-template name="insertGeneration"/>
</xsl:template>
<xsl:template match="Data/aTable">
<xsl:call-template name="insertGeneration"/>
</xsl:template>
我希望按此顺序生成输出,即在所有INSERT INTO anotherTable
之前的所有INSERT INTO aTable
。但结果顺序与源文档相同。
我需要一个特定的命令,否则在执行SQL脚本时我可能会违反外键约束。
我的xslt处理器是Visual Studio 2005.好吧,不是一个紧凑的xslt处理器; - )
答案 0 :(得分:1)
<xsl:output method="text" encoding="UTF-8" />
<xsl:template match="Data">
<xsl:apply-templates select="*/*">
<xsl:sort select="name(..)" case-order="lower-first" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Data/*/*">
<xsl:text>INSERT INTO [</xsl:text>
<xsl:value-of select="name(..)" />
<xsl:text>] (</xsl:text>
<xsl:apply-templates select="@*" mode="names" />
<xsl:text>) VALUES (</xsl:text>
<xsl:apply-templates select="@*" mode="values" />
<xsl:text>)
</xsl:text>
</xsl:template>
<xsl:template match="Data/*/*/@*" mode="names">
<xsl:text>[</xsl:text>
<xsl:value-of select="name()" />
<xsl:text>]</xsl:text>
<xsl:if test="position() < last()">, </xsl:if>
</xsl:template>
<xsl:template match="Data/*/*/@*" mode="values">
<xsl:text>'</xsl:text>
<xsl:call-template name="string-replace">
<xsl:with-param name="search">'</xsl:with-param>
<xsl:with-param name="replace">''</xsl:with-param>
</xsl:call-template>
<xsl:text>'</xsl:text>
<xsl:if test="position() < last()">, </xsl:if>
</xsl:template>
产生与T-SQL兼容的输出,如下所示:
INSERT INTO [anotherTable] ([Col3], [Col4]) VALUES ('someText', '42')
INSERT INTO [anotherTable] ([Col3], [Col4]) VALUES ('myText', '34')
INSERT INTO [aTable] ([Col1], [Col2]) VALUES ('1', 'some''Text')
INSERT INTO [aTable] ([Col1], [Col2]) VALUES ('2', 'newText')
如有必要,将代码调整为数据库的语法。
这按表名使用词典顺序。如果您需要不同的订单,请相应地更改<xsl:sort>
或使用多个单独的<xsl:apply-templates>
来生成所需的序列。 (请注意,某些XSLT处理器似乎忽略了case-order
参数。)
请注意,string-replace
是一个命名模板,它实现了一个字符串替换函数(XSLT 1.0必需)。如果你有XSLT 2.0,你可以简单地使用内置的string-replace()
函数。
<xsl:template name="string-replace">
<xsl:param name="subject" select="string()" />
<xsl:param name="search" />
<xsl:param name="replace" />
<xsl:variable name="head" select="substring-before($subject, $search)" />
<xsl:variable name="tail" select="substring-after($subject, $search)" />
<xsl:variable name="found" select="$head or $tail" />
<xsl:if test="not($found)">
<xsl:value-of select="$subject" />
</xsl:if>
<xsl:if test="$found">
<xsl:value-of select="$head" />
<xsl:value-of select="$replace" />
<xsl:call-template name="string-replace">
<xsl:with-param name="subject" select="$tail" />
<xsl:with-param name="search" select="$search" />
<xsl:with-param name="replace" select="$replace" />
</xsl:call-template>
</xsl:if>
</xsl:template>