我有一个XML,我需要将所有节点中的特定元素提取到1000个组中。实际XML的结构如下所示:
<host>
<node>
<type>fruit1</type>
<value>1</value>
</node>
<node>
<type>fruit2</type>
<value>2</value>
</node>
<node>
<type>fruit3</type>
<value>3</value>
</node>
<node>
<type>fruit4</type>
<value>4</value>
</node>
....
....
....
<node>
<type>fruit1500</type>
<value>1500</value>
</node>
</host>
我必须从所有节点中选择元素并提取到格式'fruit1','fruit2','fruit3',...,'fruit1499','fruit1500'
并将数据传递到SQL查询select * from tablename where ColumnName_type IN('fruit1','fruit2','fruit3',...,'fruit1499','fruit1500')
。问题是我无法将超过1000个值传递到SQL IN条件。
现在我必须将前1000个值分组到一个组中,然后将1000个值分组到另一个组中并将其传递给查询。预期的sql查询如下 -
select * from tablename where ColumnName_type in
('fruit1','fruit2','fruit3',...,'fruit1000') union all
select * from tablename where ColumnName_type in
('fruit1001','fruit1002',...'fruit1500')
为提取所有值而编写的XSLT如下 -
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"
encoding="UTF-8" />
<xsl:template match="/">
<html>
<body>
<table border="1">
<xsl:for-each select="//field/value/listValues/value">
<tr>
<td>
<xsl:text>'</xsl:text><xsl:value-of select="ancestor::field/code"/>
<xsl:text>'</xsl:text><xsl:if test="position()!=last()">,</xsl:if>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
任何将数据提取到群组中的建议都会有很大的帮助。
答案 0 :(得分:0)
您可以使用模数和以下兄弟轴的巧妙组合创建组或批次。在样式表下面需要像您在问题中显示的XML并输出纯文本(SQL语句):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="utf-8" indent="no" method="text"/>
<xsl:variable name="groupSize" select="1000"/>
<xsl:template match="host">
<xsl:for-each select="node[position() mod $groupSize = 1]">
<xsl:if test="position() > 1">
<xsl:text> union all
</xsl:text>
</xsl:if>
<xsl:variable name="values">
<xsl:text>'</xsl:text>
<xsl:value-of select="./type"/>
<xsl:text>'</xsl:text>
<xsl:for-each select="following-sibling::node[$groupSize > position()]/type">
<xsl:text>,'</xsl:text>
<xsl:value-of select="."/>
<xsl:text>'</xsl:text>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="concat('select * from tablename where ColumnName_type in 
(', $values, ')')"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
使用groupSize = 3的结果:
select * from tablename where ColumnName_type in
('fruit1','fruit2','fruit3') union all
select * from tablename where ColumnName_type in
('fruit4','fruit1500')
答案 1 :(得分:0)
利用关系数据库的力量重新考虑您的方法和规模。使用XSLT将XML转换为表格式格式文件,例如CSV,用于所有列出的水果。然后,将CSV作为临时表导入数据库。
实际上,每个主要的RDBMS都可以使用方便的方法轻松导入CSV:
LOAD DATA FILE...
COPY mytable FROM...
.import csv...
DoCmd.TransferText...
BULK INSERT my table...
IMPORT FROM...
最后,将临时表(即INNER JOIN
)加入到您需要的表中。这避免了重复的IN()
条款和UNION ALL
,所有这些都适用于干燥方案。
XSLT (将xml转换为csv)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/host">
<xsl:text>fruit_name
</xsl:text>
<xsl:for-each select="node">
<xsl:value-of select="type"/>
<xsl:if test="position() != last()">
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
CSV 输出
fruit_name
fruit1
fruit2
fruit3
fruit4
...
fruit1500
SQL 查询(表格与水果临时表的显式连接)
SELECT t.* FROM tablename t
INNER JOIN fruit_temptable f
ON t.ColumnName_type = f.fruit_name