我有大量(40万)大XML(200到4000行,有40个父子关系)。我想解析它们并收集它们中存在的所有节点。
使用XML
<tag1>
<tag2>
<tag3>Content3</tag3>
</tag2>
<tag2>
<tag4>Content4</tag4>
</tag2>
<tag2>
<tag4>Content4</tag4>
</tag2>
<tag2>
<tag5><tag6>Content6</tag6></tag5>
</tag2>
</tag1>
我想得到
tag1
tag1>tag2
tag1>tag2>tag3
tag1>tag2
tag1>tag2>tag4
tag1>tag2
tag1>tag2>tag4
tag1>tag2
tag1>tag2>tag5
tag1>tag2>tag5>tag6
或至少(除去叶子):
tag1
tag1>tag2
tag1>tag2
tag1>tag2
tag1>tag2
tag1>tag2>tag5
因为我的真正目标是检查节点,这些节点在目标数据库中被建模为表格。
输出可以是查询结果,表格或文件,我不介意。
最终目标是使用此数据来检查用于将XML内容加载到数据库中的SSIS是否未错过任何节点。事实上,我们知道它已经错过了一些,所以现在我们必须找到哪些。
我已检查过SQL Server 2012功能,但我有两个问题: - 它没有给我任何关于FILES性能的指针。我在使用文件时需要最快的方法,而不是在字符串中使用XML内容时 - 这有点麻烦
我已经用Qlikview做了我自己的解决方案,它检查可能的节点(我有XSD)是否在XML中并将结果输出到一个文件中,这很好但是太慢(每个XML 1到2个) ,太长了。)
谢谢你们!
答案 0 :(得分:0)
我一直在寻找没有回答tsql / xml问题并找到你的问题。这让我很好奇,不知道今天是否有任何需要,但这是我的建议:
它适用于任何深度的XML ......
我必须承认,我通常不使用CURSOR,但在这种情况下我没有找到另一种方法。如果你不介意那么测试它的速度并给出简短的答案会很好 - 只是为了好奇: - )
int corePoolSize = 400;
int maximumPoolSize = 1_000_000;
long keepaliveTimeout = 60L;
TimeUnit keepaliveUnit = TimeUnit.SECONDS;
BlockingQueue<Runnable> workQueue = new SynchronousQueue<Runnable>();
ExecutorService cachedExecutor = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepaliveTimeout,
keepaliveUnit,
workQueue);
ExecutorThreadPool threadpool = new ExecutorThreadPool(cachedExecutor);
Server server = new Server(threadpool);
结果:
DECLARE @x XML=
'<tag1>
<tag2>
<tag3>Content3</tag3>
</tag2>
<tag2>
<tag4>Content4</tag4>
</tag2>
<tag2>
<tag4>Content4</tag4>
</tag2>
<tag2>
<tag5>
<tag6>Content6</tag6>
</tag5>
</tag2>
</tag1>';
CREATE TABLE #HelpTable(NodeIndex INT UNIQUE,NextNodeName VARCHAR(100),HasChildren BIT);
CREATE TABLE #FinalTags(ID INT IDENTITY,TagNames VARCHAR(1000));
WITH RootNode AS
(
SELECT RN.value('local-name(.)','varchar(100)') AS RN_Name
,RN.query('.') AS RN_Node
FROM @x.nodes('*') AS The(RN)
)
,AnalyzeNodes AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) * 10 AS NodeIndex
,RN_Name
,TheNext.Nodes.value('local-name(.)','varchar(100)') AS NextNodeName
,CASE WHEN TheNext.Nodes.value('count(./*)','int')=0 THEN 0 ELSE 1 END AS HasChildren
FROM RootNode
CROSS APPLY RN_Node.nodes('//*') AS TheNext(Nodes)
)
INSERT INTO #HelpTable
SELECT AnalyzeNodes.NodeIndex,AnalyzeNodes.NextNodeName,AnalyzeNodes.HasChildren
FROM AnalyzeNodes
UNION ALL
SELECT an.NodeIndex+1,RN_Name,1
FROM AnalyzeNodes AS an
WHERE an.HasChildren=0
DECLARE @collect VARCHAR(1000)='';
DECLARE @tag VARCHAR(100);
DECLARE @children BIT;
DECLARE cur CURSOR FAST_FORWARD
FOR
SELECT NextNodeName,HasChildren
FROM #HelpTable
ORDER BY NodeIndex;
OPEN cur;
FETCH NEXT FROM cur INTO @tag,@children
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO #FinalTags VALUES(@collect + '>' + @tag);
IF @children=0
SET @collect='';
ELSE
SET @collect=@collect + '>' + @tag;
FETCH NEXT FROM cur INTO @tag,@children
END
CLOSE cur;
DEALLOCATE cur;
SELECT SUBSTRING(TagNames,2,1000) AS TagNames
FROM #FinalTags
WHERE ID=1 OR TagNames<>(SELECT ft.TagNames FROM #FinalTags AS ft WHERE ft.ID=1)
ORDER BY ID,TagNames;
DROP TABLE #FinalTags;
DROP TABLE #HelpTable;