2013-10-23 28 views
0

的XSLT输出我有一个大的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") 

我已经从一个“表”到相应的SQL语句的转变,但在文档的同一顺序生成XSLT输出。

有没有办法在aTable之前有另一个例子anotherTable?

编辑

感谢您的意见和答复。读他们我意识到我原来的问题不是很清楚。我会尝试添加更多细节。

我已经生成了一个模板,可以在插入语句序列中正确转换xml数据,假设这个模板名为“insertGeneration”。

然后我写的东西,如:

<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 aTable之前的所有INSERT INTO anotherTable。但结果顺序与源文档相同。

我需要一个特定的顺序,否则我可能会违反执行SQL脚本时的外键约束。

我的XSLT处理器是Visual Studio 2005的嘛,没有正确紧凑XSLT处理器;-)

+0

这将有助于看到您目前的转变。 – hielsnoppe

回答

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>)&#xA;</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() &lt; 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() &lt; 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> 
+0

感谢您的详细和有用的答案,但这不是我的意图。这是我的错,这个问题不是很清楚。我会尽力改善它...... – sblandin

+0

即使你不会使用我的答案的其余部分,你可以使用明显的指针'',不是吗?可以对'和''进行排序。 – Tomalak

+0

是的,但排序不是按字母顺序的我需要对输出进行排序,以便在启动生成的SQL脚本时,我不违反任何外键约束 – sblandin