在SQL Server中选择嵌套XML中的元素

时间:2017-11-09 14:53:04

标签: sql sql-server xml xpath

我在SQL Server表中有一个包含XML内容的列。

实际上,在这个特定的XML列中将几个不同的XML合并在一起。

当我这样做时

select
    columnwithXML.query('(/root/secondlayer/node())').value('(/*)[11]', 'varchar(max)')

我实际上得到了一个我真正需要的XML,它从这开始:

<?xml version="1.0" encoding="utf-16"?>
<thirdlayer xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <someVariable1>false</someVariable1>
    <someVariable2>false</someVariable2>

顺便说一句:<thirdlayer>级别上有很多兄弟姐妹。我只对这个感兴趣。我现在用[11]达到那个。

我想阅读someVariable2的内容。我尝试了很多不同的选项,但大多数都返回NULL。我不太确定如何构建XML路径,特别是从那以后。

如果有人有建议,那将非常感激。

提前谢谢

补充:XML的一部分。我拿出部分内容使其更容易阅读。

<Configurations><Config><Label>IYE</Label><Value>Ja</Value><Description>xxxx</Description></Config><Config><Label>xxxx</Label><Value><?xml version="1.0" encoding="utf-16"?> <ArrayOfxxxx xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <ProductOption> (...) </ProductOption> <ProductOption> (...) </ProductOption> </ArrayOfyyyyy></Value><Description/> </Config><Config><Label>TICKET</Label><Value><?xml version="1.0" encoding="utf-8"?> <Ticket xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Sections> (...) </Sections> <PriceSections> (...) </PriceSections> </Ticket></Value><Description/></Config><Config><Label>CONFIGURATION</Label><Value><?xml version="1.0" encoding="utf-16"?> <ConfigurationData xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <VariableX>false</VariableX> <VariableY>false</VariableY> </ConfigurationData></Value><Description/></Config></Configurations>

我能够到达我只有的地方:

<ConfigurationData xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <VariableX>false</VariableX> <VariableY>false</VariableY> </ConfigurationData>

然后我被卡住了。

1 个答案:

答案 0 :(得分:1)

在SQL Server中,您的xml无法存储为XML(由于内部放置了text/xmldecl个元素(<?xml version="1.0" encoding="utf-8"?>)。这是 - 通常会说 - 不允许。

我不知道你是如何设法达到

  

我能够到达我只有......的部分。

你是用字符串方法做的吗?

谁在创建这些XML?如果这是你的控制,你应该在没有声明的情况下这样做。或者(并且不推荐)您可以将所有嵌入式XML包含在CDATA中并将其作为字符串读取(性能不佳,因为您必须将其转换为XML)。

现有XML的解决方案

你可以像我在这里一样对字符串进行攻击:

DECLARE @YourXML NVARCHAR(MAX)=
N'<Configurations><Config><Label>IYE</Label><Value>Ja</Value><Description>xxxx</Description></Config><Config><Label>xxxx</Label><Value><?xml version="1.0" encoding="utf-16"?>
<ArrayOfxxxx xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ProductOption>
    (...)
  </ProductOption>
  <ProductOption>
    (...)
  </ProductOption>
</ArrayOfxxxx></Value><Description/>
</Config><Config><Label>TICKET</Label><Value><?xml version="1.0" encoding="utf-8"?>
<Ticket xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Sections>
        (...)
    </Sections>
    <PriceSections>
     (...)
    </PriceSections>
    </Ticket></Value><Description/></Config><Config><Label>CONFIGURATION</Label><Value><?xml version="1.0" encoding="utf-16"?>
<ConfigurationData xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <VariableX>false</VariableX>
  <VariableY>false</VariableY>
</ConfigurationData></Value><Description/></Config></Configurations>';

- 我使用REPLACE两次将声明转换为注释 - 然后我使用.query()来阅读<Config>为“{配置”的<Label>元素。
- 接下来我转到ConfigurationData并从CTE返回。

WITH GetMyNode(ConfigurationData) AS
(
    SELECT CAST(REPLACE(REPLACE(@YourXML,'<?','<!--?'),'?>','?-->') AS XML)
           .query('/Configurations/Config[(Label/text())[1]="CONFIGURATION"]/Value/ConfigurationData')
)
--read the CTEs XML and retrieve the two Variables
SELECT ConfigurationData.value('(ConfigurationData/VariableX/text())[1]','nvarchar(max)') AS VariableX
      ,ConfigurationData.value('(ConfigurationData/VariableY/text())[1]','nvarchar(max)') AS VariableY
FROM GetMyNode