使用SQL Server从复杂的XML结构中读取值

问题描述:

我想从数据类型为ntext的列中读取XML结构中的SQL Server查询中的值。使用SQL Server从复杂的XML结构中读取值

这是我想提取VALUE TO READ!!! XML结构:

<PrinterProcessDef xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://dev.docuware.com/settings/workflow/processdef" Id="3e62848d-040e-4f4c-a893-ed85a7b2878a" Type="PrinterProcess" ConfigId="c43792ed-1934-454b-a40f-5f4dfec933b0" Enabled="true" PCId="2837f136-028d-47ed-abdc-4103bedce1d2" Timestamp="2016-08-08T09:44:38.532415"> 
    <Configs> 
    <Config xmlns:q1="http://dev.docuware.com/settings/workflow/processconfig" xsi:type="q1:PrinterProcessConfig" Id="c43792ed-1934-454b-a40f-5f4dfec933b0" /> 
    <Config xmlns:q2="http://dev.docuware.com/settings/workflow/processconfig" xsi:type="q2:RecognizeActConfig" Id="b89a6fc2-5573-4034-978a-752c6c0de4cf"> 
     <q2:Header DefaultRecognitionTechnology="OCR" DefaultOCRSettingsGuid="00000000-0000-0000-0000-000000000000"> 
     </q2:Header> 
     <q2:Body> 
     <q2:AnchorDefs /> 
     <q2:ZoneDefs /> 
     <q2:TableDefs /> 
     <q2:FaceLayouts> 
     </q2:FaceLayouts> 
     <q2:FaceSamples> 
     </q2:FaceSamples> 
     <q2:SampleDocument> 
      <MetaData xmlns="http://dev.docuware.com/settings/common" FileName="Test - Editor" MimeType="application/pdf" PageCount="1" SourceAppName="C:\Windows\system32\NOTEPAD.EXE" DocumentTitle="Test - Editor" PdfCreator="DocuWare Printer" /> 
      <Data xmlns="http://dev.docuware.com/settings/common">!!!VALUE TO READ!!!</Data> 
     </q2:SampleDocument> 
     </q2:Body> 
     <q2:AllPagesRequired>false</q2:AllPagesRequired> 
    </Config> 
    <Config xmlns:q3="http://dev.docuware.com/settings/workflow/processconfig" xsi:type="q3:RecognizeActConfig" Id="db5b195d-79e4-4804-bd38-f4fc7e8d5a8d"> 
    </Config> 
    <Config xmlns:q4="http://dev.docuware.com/settings/workflow/processconfig" xsi:type="q4:AddOverlayActConfig" Id="023aab08-c6e3-4f08-9d26-0175d1564ef2"> 
     <q4:Overlays /> 
    </Config> 
    <Config xmlns:q5="http://dev.docuware.com/settings/workflow/processconfig" xsi:type="q5:PrintActConfig" Id="4a4ec06a-8652-4777-84d2-53cb862b3328"> 
    </Config> 
    <Config xmlns:q6="http://dev.docuware.com/settings/workflow/processconfig" xsi:type="q6:SignActConfig" Id="8c030961-e68e-4c2f-83f1-cac20f51d4d6"> 
    </Config> 
    <Config xmlns:q7="http://dev.docuware.com/settings/workflow/processconfig" xsi:type="q7:EmailActConfig" Id="5dbd144b-5c33-407a-b638-e062f9045fb4"> 
    </Config> 
    <Config xmlns:q8="http://dev.docuware.com/settings/workflow/processconfig" xsi:type="q8:IndexActConfig" Id="f2a70e07-d76e-4e82-9313-7c665df4c311"> 
    </Config> 
    <Config xmlns:q10="http://dev.docuware.com/settings/workflow/processconfig" xsi:type="q10:StoreActConfig" Id="ff8aec66-608e-4dde-a4b6-de65ada39bb0"> 
    </Config> 
    <Config xmlns:q11="http://dev.docuware.com/settings/workflow/processconfig" xsi:type="q11:NotifyUserActConfig" Id="7ffb0437-6b8c-4f5f-8f40-434f4a6d609a" /> 
    </Configs> 
    <Activities> 
    </Activities> 
</PrinterProcessDef> 

这是SQL查询我所用:

SELECT 
    CAST([Table].[settings] as xml) 
     .value('declare namespace q2="http://dev.docuware.com/settings/workflow/processconfig"; 
     (/PrinterProcessDef/Configs/Config[@xsi:type="q2:RecognizeActConfig"]/q2:Body/q2:SampleDocument/Data/text())[1]', 
     'varchar(max)') 
FROM 
    [DB].[dbo].[Table] 

我得到的返回是一个NULL,而不是希望 - 对于VALUE TO READ!!!

我应该怎么做才能使查询工作?

我也试过不同的版本没有名称空间声明和其他人,但我总是得到NULL。

+0

'ntext', 'text'和'image'数据类型将在未来版本的SQL Server中删除。避免在新的开发工作中使用这些数据类型,并计划修改当前正在使用它们的应用程序。改为使用'nvarchar(max)','varchar(max)'和'varbinary(max)'。 [在此处查看详细信息](http://msdn.microsoft.com/en-us/library/ms187993.aspx) - 或者在这种情况下,如果您要存储XML - 那么**使用** XML数据类型!这就是它的原因! –

所有元素都有名称空间定义。您需要根据定义声明并指定它们

SELECT CAST([Table].[settings] as xml).value(
    'declare namespace top="http://dev.docuware.com/settings/workflow/processdef"; 
    declare namespace q2="http://dev.docuware.com/settings/workflow/processconfig"; 
    declare namespace nd="http://dev.docuware.com/settings/common"; 
    (/top:PrinterProcessDef/top:Configs/top:Config[@xsi:type="q2:RecognizeActConfig"]/q2:Body/q2:SampleDocument/nd:Data)[1]', 
     'varchar(max)') 
FROM [DB].[dbo].[Table] 
+0

由于在这种情况下给出了奇怪的命名空间,我宁愿建议避免(掩盖)它们... – Shnugo

您忘记了使用xmlns属性声明的名称空间。看看下面的例子:

DECLARE @xml xml = 'yourXml' 

SELECT @xml.value(' 
declare namespace q2="http://dev.docuware.com/settings/workflow/processconfig"; 
declare namespace g="http://dev.docuware.com/settings/workflow/processdef"; 
declare namespace qd="http://dev.docuware.com/settings/common"; 
(//g:PrinterProcessDef/g:Configs/g:Config[@xsi:type="q2:RecognizeActConfig"]/q2:Body/q2:SampleDocument/qd:Data/text())[1]', 
    'varchar(max)') 
+0

在这种情况下,我给出了奇怪的命名空间,我宁愿建议避免(掩盖)它们... – Shnugo

但是生成此XML,命名空间是很奇怪......你有相同的命名空间中声明了个遍......如果我没有得到这个错误,命名空间是不是真正的事情应该是这样,所以我会忽略它们:

SELECT 
    CAST([Table].[settings] as xml as xml) 
     .value('(/*:PrinterProcessDef/*:Configs/*:Config[@*:type="q2:RecognizeActConfig"]/*:Body/*:SampleDocument/*:Data/text())[1]', 
     'varchar(max)') 
FROM 
    [DB].[dbo].[Table] 

反正我劝你申报WITH XMLNAMESPACE内的命名空间,而不是.value -function内。如果你需要一个以上的值超出这个,你可以创建更好的阅读查询:

WITH XMLNAMESPACES(DEFAULT 'http://dev.docuware.com/settings/workflow/processdef' 
        ,'http://dev.docuware.com/settings/workflow/processconfig' AS q2 
        ,'http://dev.docuware.com/settings/common' AS nd) 
SELECT 
    CAST([Table].[settings] as xml) 
     .value('(/PrinterProcessDef/Configs/Config[@xsi:type="q2:RecognizeActConfig"]/q2:Body/q2:SampleDocument/nd:Data)[1]', 
     'varchar(max)') 

BTW:使用DEFAULT避免了虚拟命名空间像在其他的答案top: ...