【问题标题】:Putting different elements into one column from xml in SQL Server从 SQL Server 中的 xml 将不同的元素放入一列
【发布时间】:2020-02-11 11:10:42
【问题描述】:

我有一个 XML 文档的以下部分:

    <?xml version="1.0" encoding="ISO-8859-1" ?>
    <IPCScheme xmlns="http://depatisnet.dpma.de/ipc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://depatisnet.dpma.de/ipc ipc_scheme_3-1_dpma.xsd" edition="20190101" lang="EN">
       <ipcEntry  symbol="A01D0000000000" kind="u" entryType="K">
           <textBody><title>
               <titlePart>
                   <text> HARVESTING </text>
               </titlePart>
               <titlePart>
                   <text> MOWING</text>
               </titlePart>
           </title></textBody>
       </ipcEntry>
       <ipcEntry  symbol="A01F0000000000" kind="u" entryType="K">
           <textBody><title>
               <titlePart>
                   <text> THRESHING</text>
                   <entryReference> combines 
                       <sref ref="A01D0041000000"></sref>
                   </entryReference>
               </titlePart>
               <titlePart>
                   <text> BALING OF STRAW, HAY OR THE LIKE</text>
               </titlePart>
               <titlePart>
                   <text> STATIONARY APPARATUS OR HAND TOOLS FOR FORMING OR BINDING STRAW, HAY OR THE LIKE INTO BUNDLES</text>
               </titlePart>
               <titlePart>
                   <text> CUTTING OF STRAW, HAY OR THE LIKE</text>
               </titlePart>
               <titlePart>
                   <text> STORING AGRICULTURAL OR HORTICULTURAL PRODUCE</text>
                   <entryReference> arrangements for making or setting stacks in connection with harvesting 
                       <sref ref="A01D0085000000"></sref>
                   </entryReference>
               </titlePart>
           </title></textBody>
       </ipcEntry>
       <ipcEntry symbol="A01B0000000000" kind="u" entryType="K">
           <textBody><title>
               <titlePart>
                    <text> SOIL WORKING IN AGRICULTURE OR FORESTRY</text>
               </titlePart>
               <titlePart>
                   <text> PARTS, DETAILS, OR ACCESSORIES OF AGRICULTURAL MACHINES OR IMPLEMENTS, IN GENERAL</text>
                   <entryReference> making or covering furrows or holes for sowing, planting or manuring 
                       <sref ref="A01C0005000000"></sref>
                   </entryReference>
                   <entryReference> machines for harvesting root crops 
                       <sref ref="A01D0000000000"></sref>
                   </entryReference>
                   <entryReference> mowers convertible to soil working apparatus or capable of soil working
                       <sref ref="A01D0042040000"></sref>
                   </entryReference>
                   <entryReference> mowers combined with soil working implements 
                       <sref ref="A01D0043120000"></sref>
                   </entryReference>
                   <entryReference>soil working for engineering purposes 
                       <sref ref="E01"></sref> , 
                       <sref ref="E02"></sref> , 
                       <sref ref="E21"></sref>
                   </entryReference>
               </titlePart>
           </title></textBody>
       </ipcEntry>
 </IPCScheme>

目标是有一个带有符号的列和一个带有连接文本的列,包括每个 ipc 条目的信息。

Symbol          String
A01B0000000000  SOIL WORKING IN AGRICULTURE OR FORESTRY; PARTS, DETAILS, OR ACCESSORIES OF AGRICULTURAL MACHINES OR IMPLEMENTS, IN GENERAL (making or covering furrows or holes for sowing, planting or manuring A01C 5/00; machines for harvesting root crops A01D; mowers convertible to soil working apparatus or capable of soil working A01D 42/04; mowers combined with soil working implements A01D 43/12; soil working for engineering purposes E01, E02, E21)
A01D0000000000  HARVESTING; MOWING
A01F0000000000  THRESHING (combines A01D 41/00); BALING OF STRAW, HAY OR THE LIKE; STATIONARY APPARATUS OR HAND TOOLS FOR FORMING OR BINDING STRAW, HAY OR THE LIKE INTO BUNDLES; CUTTING OF STRAW, HAY OR THE LIKE; STORING AGRICULTURAL OR HORTICULTURAL PRODUCE (arrangements for making or setting stacks in connection with harvesting A01D 85/00)

我已经进行了一个查询,该查询不包括最后一个分隔符,并且仅在创建条目引用时包含括号,因此对于我们没有条目引用的符号没有“()”。但是为了简单起见,因为问题是包含查询本身,我将这部分留在了以下查询中。

    DECLARE @xml  XML
    Select @xml =P
    FROM OPENROWSET (BULK 'C:\Users\File.xml', SINGLE_BLOB) AS Products(P)
    ;WITH XMLNAMESPACES(DEFAULT 'http://depatisnet.dpma.de/ipc',
                            'http://www.w3.org/2001/XMLSchema-instance' as xsi)
    SELECT
        MY_XML.IPC.value('@symbol', 'NVARCHAR(max)') as Symbol,
        concat(left(MY_XML.IPC.query('for $i in textBody/title/titlePart/text return concat($i, ";")').value('.','NVARCHAR(max)'), len(MY_XML.IPC.query('for $i in textBody/title/titlePart/text return concat($i, ";")').value('.','NVARCHAR(max)'))-1),' (',My_XML.IPC.query('for $i in textBody/title/titlePart/entryReference return concat($i, ($i/sref/@ref)[1] , ";")').value('.','NVARCHAR(max)'),')') as String
    FROM @xml.nodes('IPCScheme/ipcEntry/ipcEntry/ipcEntry') MY_XML(IPC)

结果如下:

    Symbol         String
    A01B0000000000 SOIL WORKING IN AGRICULTURE OR FORESTRY; PARTS, DETAILS, OR ACCESSORIES OF AGRICULTURAL MACHINES OR IMPLEMENTS, IN GENERAL (making or covering furrows or holes for sowing, planting or manuring A01C0005000000; ; machines for harvesting root crops A01D0000000000; mowers convertible to soil working apparatus or capable of soil working A01D0042040000; mowers combined with soil working implements A01D0043120000; soil working for engineering purposes  ,  , E01;)
    A01D0000000000 HARVESTING; MOWING ()
    A01F0000000000 THRESHING;  BALING OF STRAW, HAY OR THE LIKE; STATIONARY APPARATUS OR HAND TOOLS FOR FORMING OR BINDING STRAW, HAY OR THE LIKE INTO BUNDLES; CUTTING OF STRAW, HAY OR THE LIKE; STORING AGRICULTURAL OR HORTICULTURAL PRODUCE (combines A01D0041000000; arrangements for making or setting stacks in connection with harvesting A01D0085000000;)

所以所有 entryReferences 都是通过构造添加到文本末尾的,当 entryReferences 添加到最后一个 titlePart 时是正确的,但通常不是,另外我只能包含一个 sref/@ref。我需要的是某种查询,它查询每个标题部分的不同元素,并以我想要的方式将其添加到完整的字符串中。

编辑: 总而言之,我想要每个 ipcEntry 属性符号和每个 ipcEntry 一个组合文本,其中每个 titlePart 元素文本后跟“(”,entryReference 和来自 sref 的属性@ref 后跟“);”和下一个标题部分。所有元素都可以有多个文本,entryReference 或 sref,这使得这在某种程度上具有挑战性。 xml 片段之后的第一个表是我想要的。我得到的是 sql-code 之后的第二个表。

希望您能对此提出一些想法。提前致谢

@Shnugo 的解决方案略有编辑

 ;WITH XMLNAMESPACES(DEFAULT 'http://depatisnet.dpma.de/ipc')
 SELECT entr.value('@symbol','nvarchar(100)') AS Symbol
       ,STUFF(
        (
        SELECT CONCAT('; ',B.tp.value('(text/text())[1]','nvarchar(100)'))
              ,CASE WHEN B.tp.exist('entryReference')=1 THEN
               CONCAT(' ('
                      ,STUFF(
                       (
                        SELECT CONCAT('; ',C.er.value('text()[1]','nvarchar(100)'))
                            ,CASE WHEN C.er.exist('sref')=1 THEN
                            STUFF(
                                (
                                 Select Concat(', ', D.ad.value('@ref[1]','nvarchar(100)'))
                                 From C.er.nodes('sref') D(ad)
                                 For XML PATH('')
                                 ),1,2,'') End
                        FROM B.tp.nodes('entryReference') C(er)
                        FOR XML PATH('')
                       ),1,2,'')
                      ,')') END
        FROM A.entr.nodes('textBody/title/titlePart') B(tp)
        FOR XML PATH('')
        ),1,1,'') AS ConcatenatedTextNodes 
 FROM @xml.nodes('/IPCScheme/ipcEntry') A(entr);

【问题讨论】:

  • 你能发布有效的xml吗?我将您的示例复制到我机器上的 xml 文件中并运行您的代码。 “消息 9410,级别 16,状态 1,第 2 行 XML 解析:第 38 行,字符 50,需要空格”
  • @SeanLange 行:&lt;ipcEntry symbol="A01B0000000000" kind="u"entryType="K"&gt;... 在 "u" 和 "entryType="K" 之间放置一个空格...例如在本例中的 "u" 后面有空格 ^^^
  • 您的问题措辞非常混乱。你能提供你期望从这个 XML 片段得到的结果吗?
  • @AlanBurstein 你是对的。我编辑了 xml 片段,现在它应该可以工作了。很抱歉没有再次测试。
  • @RogerWolf 这是我的第一个,所以是的,肯定还有很长的路要走。我想要 xml 片段之后的表中的结果。使用我发布的代码,我只能在 sql 代码之后获得表格。我需要同时查询 text 和 entryReference 元素以及 sref 属性,但我只能通过它们单独查询。

标签: sql-server xml tsql sql-server-2012 xquery


【解决方案1】:

有很多方法可以解决这个问题:

假设您的 XML 被读入一个 xml 类型变量(提示:去掉&lt;??&gt; 声明):

DECLARE @xml XML=
N'<IPCScheme xmlns="http://depatisnet.dpma.de/ipc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://depatisnet.dpma.de/ipc ipc_scheme_3-1_dpma.xsd" edition="20190101" lang="EN">
       <ipcEntry  symbol="A01D0000000000" kind="u" entryType="K">
           <textBody><title>
               <titlePart>
                   <text> HARVESTING </text>
               </titlePart>
               <titlePart>
                   <text> MOWING</text>
               </titlePart>
           </title></textBody>
       </ipcEntry>
       <ipcEntry  symbol="A01F0000000000" kind="u" entryType="K">
           <textBody><title>
               <titlePart>
                   <text> THRESHING</text>
                   <entryReference> combines 
                       <sref ref="A01D0041000000"></sref>
                   </entryReference>
               </titlePart>
               <titlePart>
                   <text> BALING OF STRAW, HAY OR THE LIKE</text>
               </titlePart>
               <titlePart>
                   <text> STATIONARY APPARATUS OR HAND TOOLS FOR FORMING OR BINDING STRAW, HAY OR THE LIKE INTO BUNDLES</text>
               </titlePart>
               <titlePart>
                   <text> CUTTING OF STRAW, HAY OR THE LIKE</text>
               </titlePart>
               <titlePart>
                   <text> STORING AGRICULTURAL OR HORTICULTURAL PRODUCE</text>
                   <entryReference> arrangements for making or setting stacks in connection with harvesting 
                       <sref ref="A01D0085000000"></sref>
                   </entryReference>
               </titlePart>
           </title></textBody>
       </ipcEntry>
       <ipcEntry symbol="A01B0000000000" kind="u" entryType="K">
           <textBody><title>
               <titlePart>
                    <text> SOIL WORKING IN AGRICULTURE OR FORESTRY</text>
               </titlePart>
               <titlePart>
                   <text> PARTS, DETAILS, OR ACCESSORIES OF AGRICULTURAL MACHINES OR IMPLEMENTS, IN GENERAL</text>
                   <entryReference> making or covering furrows or holes for sowing, planting or manuring 
                       <sref ref="A01C0005000000"></sref>
                   </entryReference>
                   <entryReference> machines for harvesting root crops 
                       <sref ref="A01D0000000000"></sref>
                   </entryReference>
                   <entryReference> mowers convertible to soil working apparatus or capable of soil working
                       <sref ref="A01D0042040000"></sref>
                   </entryReference>
                   <entryReference> mowers combined with soil working implements 
                       <sref ref="A01D0043120000"></sref>
                   </entryReference>
                   <entryReference>soil working for engineering purposes 
                       <sref ref="E01"></sref> , 
                       <sref ref="E02"></sref> , 
                       <sref ref="E21"></sref>
                   </entryReference>
               </titlePart>
           </title></textBody>
       </ipcEntry>
 </IPCScheme>';

--最简单的方法是 XQuery 的data()。但这在任何情况下都会使用空格作为分隔符。可惜不能设置分隔符作为参数。

 WITH XMLNAMESPACES(DEFAULT 'http://depatisnet.dpma.de/ipc')
 SELECT entr.value('@symbol','nvarchar(100)') AS Symbol
       ,entr.query('data(.//text)').value('.','nvarchar(max)') AS ConcatenatedTextNodes
 FROM @xml.nodes('/IPCScheme/ipcEntry') A(entr);

--这将使用嵌套的FOR XML PATH('') 来模拟分组连接,并使用STUFF() 来切除前导;
--优势:她我可以轻松使用TRIM()(旧版本为LTRIM()和RTRIM())。

 WITH XMLNAMESPACES(DEFAULT 'http://depatisnet.dpma.de/ipc')
 SELECT entr.value('@symbol','nvarchar(100)') AS Symbol
       ,STUFF(
        (
        SELECT CONCAT('; ',TRIM(t.value('text()[1]','nvarchar(100)')))
        FROM entr.nodes('./textBody/title/titlePart/text') B(t)
        FOR XML PATH('')
        ),1,1,'') AS ConcatenatedTextNodes 
 FROM @xml.nodes('/IPCScheme/ipcEntry') A(entr);

--这与上面大致相同,但使用了 XQuery 的 FLWOR 方法:

 WITH XMLNAMESPACES(DEFAULT 'http://depatisnet.dpma.de/ipc')
 SELECT entr.value('@symbol','nvarchar(100)') AS Symbol
       ,STUFF(
        entr.query('for $t in ./textBody/title/titlePart/text/text()
                    return <t>{concat(";",$t)}</t>')
            .value('.','nvarchar(max)'),1,1,'') AS ConcatenatedTextNodes
 FROM @xml.nodes('/IPCScheme/ipcEntry') A(entr);

--最后,如果你已经幸运地使用了 v2017,你可以使用STRING_AGG()

 WITH XMLNAMESPACES(DEFAULT 'http://depatisnet.dpma.de/ipc')
 ,cte AS
 (
     SELECT entr.value('@symbol','nvarchar(100)') AS Symbol
           ,t.value('text()[1]','nvarchar(max)') AS TextNode
     FROM @xml.nodes('/IPCScheme/ipcEntry') A(entr)
     CROSS APPLY A.entr.nodes('./textBody/title/titlePart/text') B(t)
 )
 SELECT Symbol
       ,STRING_AGG(TextNode,';')
 FROM cte
 GROUP BY Symbol; 

更新对不起,我应该更仔细地阅读你自己的尝试......

您可以尝试一些方法来获取组合值:

WITH XMLNAMESPACES(DEFAULT 'http://depatisnet.dpma.de/ipc')
 SELECT entr.value('@symbol','nvarchar(100)') AS Symbol
       ,STUFF(
        (
        SELECT CONCAT('; ',TRIM(B.tp.value('(text/text())[1]','nvarchar(100)')))
              ,CASE WHEN B.tp.exist('entryReference')=1 THEN
               CONCAT(' ('
                      ,STUFF(
                       (
                        SELECT CONCAT('; ',TRIM(C.er.value('text()[1]','nvarchar(100)')))
                        FROM B.tp.nodes('entryReference') C(er)
                        FOR XML PATH('')
                       ),1,2,'')
                      ,')') END
        FROM A.entr.nodes('textBody/title/titlePart') B(tp)
        FOR XML PATH('')
        ),1,1,'') AS ConcatenatedTextNodes 
 FROM @xml.nodes('/IPCScheme/ipcEntry') A(entr);

遗憾的是,在 XQuery FLWOR 中我们没有 normalize-space() 或 trim(),所以嵌入的空白会搞砸。

上述解决方案使用CASE WHEN 将() 仅添加到titleParts,其中至少有一个&lt;entryReference&gt;。

【讨论】:

  • 感谢您的回答。我使用的是 2012 版本。我不仅需要文本元素,还需要括号中带有 sref/@ref 的 entryReference 元素,就像在 xml 片段之后的第一个表中一样。
  • 非常合适。我还需要 sref 元素中的属性,但我只是在您更新的代码中添加了另一个级别。我想我不能在我的版本中使用修剪功能,但这完全没有问题。首先它看起来不是很直观,但我想我会处理它。我将我的完整代码添加到问题中。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
相关资源
最近更新 更多