SQL XML-从xml列读取值

时间:2018-11-21 08:33:03

标签: sql-server xml

我无法从数据库中查询xml。 数据库中的原始列的类型为ntext,但是xml文本存储在此列中。 当我将列转换为xml类型时,这是结果之一:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.desoft.de/activerepo/fileprops">
  <props>
    <prop ns="ARM:" elem="_NoFilter">
      <value xsi:type="xsd:boolean">true</value>
    </prop>
    <prop ns="DAV:" elem="displayname">
      <value xsi:type="xsd:string">RE: Demande de Rendez vous pour le 31 Janvier</value>
    </prop>
    <prop ns="DAV:" elem="getcontenttype">
      <value xsi:type="xsd:string">message/rfc822</value>
    </prop>
    <prop ns="DAV:" elem="creationdate">
      <value xsi:type="xsd:dateTime">2018-10-18T18:41:41.3993879</value>
    </prop>
    <prop ns="tm:mail:" elem="account">
      <value xsi:type="xsd:string">mailjournal@gg.com</value>
    </prop>
    <prop ns="tm:mail:" elem="journal">
      <value xsi:type="xsd:boolean">true</value>
    </prop>
    <prop ns="tm:mail:" elem="box">
      <value xsi:type="xsd:string">Inbox</value>
    </prop>
    <prop ns="tm:mail:" elem="onlyattachments">
      <value xsi:type="xsd:boolean">false</value>
    </prop>
    <prop ns="tm:mail:" elem="user">
      <value xsi:type="xsd:string">mailjournal@gg.com</value>
    </prop>
    <prop ns="urn:schemas:httpmail:" elem="attachments">
      <value xsi:type="xsd:boolean">true</value>
    </prop>
    ...
  </props>
</root>

现在,我必须从xml列中读取单个节点的值,但实际上这不起作用,我也不知道为什么。

select
    top 10
    cast(properties as xml),
    cast(properties as xml).value('(/props/prop[@elem="displayname"]/value)[1]', 'nvarchar(255)') as testRead,
    *
from   
       tm_cas_files f (nolock)
where
       properties is not null     
       and id = '64A663EF-A466-4EB0-97DC-94554ADFDFC9'

如果我尝试以此方式读取xml,则列testRead始终为null。 对我有什么提示吗?预先感谢您的评论和帮助。

3 个答案:

答案 0 :(得分:1)

您需要在此处声明默认名称空间,就像在XML中声明的那样。这将为您提供所需的结果:

CREATE TABLE dbo.SampleTable (nXML ntext);
INSERT INTO dbo.SampleTable (nXML)
VALUES 
(N'<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.desoft.de/activerepo/fileprops">
  <props>
    <prop ns="ARM:" elem="_NoFilter">
      <value xsi:type="xsd:boolean">true</value>
    </prop>
    <prop ns="DAV:" elem="displayname">
      <value xsi:type="xsd:string">RE: Demande de Rendez vous pour le 31 Janvier</value>
    </prop>
    <prop ns="DAV:" elem="getcontenttype">
      <value xsi:type="xsd:string">message/rfc822</value>
    </prop>
    <prop ns="DAV:" elem="creationdate">
      <value xsi:type="xsd:dateTime">2018-10-18T18:41:41.3993879</value>
    </prop>
    <prop ns="tm:mail:" elem="account">
      <value xsi:type="xsd:string">mailjournal@gg.com</value>
    </prop>
    <prop ns="tm:mail:" elem="journal">
      <value xsi:type="xsd:boolean">true</value>
    </prop>
    <prop ns="tm:mail:" elem="box">
      <value xsi:type="xsd:string">Inbox</value>
    </prop>
    <prop ns="tm:mail:" elem="onlyattachments">
      <value xsi:type="xsd:boolean">false</value>
    </prop>
    <prop ns="tm:mail:" elem="user">
      <value xsi:type="xsd:string">mailjournal@gg.com</value>
    </prop>
    <prop ns="urn:schemas:httpmail:" elem="attachments">
      <value xsi:type="xsd:boolean">true</value>
    </prop>
    ...
  </props>
</root>');

GO
WITH XMLNAMESPACES(DEFAULT 'http://www.desoft.de/activerepo/fileprops', 'http://www.w3.org/2001/XMLSchema-instance' AS xsi,'http://www.w3.org/2001/XMLSchema' AS xsd)
SELECT X.XMLData.value('(root/props/prop[2]/value/text())[1]','varchar(50)') AS [value]
FROM dbo.SampleTable ST
     CROSS APPLY (VALUES(CONVERT(xml,ST.nXML))) X(XMLData);

GO
DROP TABLE dbo.SampleTable;
GO

答案 1 :(得分:0)

我现在已经根据您的提示使它起作用。另一个问题是XML文本中有换行符。这些也必须删除。 xml声明也是文本的一部分。我也删除了这个。然后它起作用了。这是最终代码:

WITH XMLNAMESPACES(DEFAULT 'http://www.desoft.de/activerepo/fileprops', 'http://www.w3.org/2001/XMLSchema-instance' AS xsi,'http://www.w3.org/2001/XMLSchema' AS xsd)
select
    top 10
    cast(replace(replace(cast(properties as nvarchar(max)),CHAR(13) + CHAR(10),''),'<?xml version="1.0" encoding="utf-16"?>','') as xml).value('(root/props/prop[@elem="from"]/value)[1]', 'nvarchar(max)')
from   
       tm_cas_files f (nolock)
where
       properties is not null     
       and id = '64A663EF-A466-4EB0-97DC-94554ADFDFC9'

非常感谢您的帮助!

答案 2 :(得分:-1)

使用XMLQuire来处理xml告诉我答案的路径以root开头:

/root/props/prop[2]/value

所以你想要'(/root/props/prop[@elem="displayname"]/value)[1]'

XMLQuire has point-and-click 'show me the XPAth'