2016-08-08 41 views
4

Ich versuche, einen Wert in einer SQL Server-Abfrage aus einer XML-Struktur aus einer Spalte des Datentyps ntext zu lesen.Wert aus einer komplexen XML-Struktur mit SQL Server lesen

Dies ist die XML-Struktur, aus dem ich VALUE TO READ!!! extrahieren möchten:

<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> 

Und das ist die SQL-Abfrage, die ich verwendet:

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] 

Alles, was ich zurück bekommen, ist eine NULL und nicht zu hoffen, -für VALUE TO READ!!!.

Was soll ich tun, damit die Abfrage funktioniert?

Ich habe auch verschiedene Versionen ohne Namespace-Deklaration und andere versucht, aber ich bekomme immer NULL.

+0

'ntext', Die Datentypen 'text' und' image' werden in einer zukünftigen Version von SQL Server entfernt. Vermeiden Sie die Verwendung dieser Datentypen in neuen Entwicklungsarbeiten, und planen Sie, Anwendungen zu ändern, die sie derzeit verwenden. Verwenden Sie stattdessen 'nvarchar (max)', 'varchar (max)' und 'varbinary (max)'. [Siehe Details hier] (http://msdn.microsoft.com/en-us/library/ms187993.aspx) - oder in diesem Fall, wenn Sie XML speichern - dann verwenden ** den XML-Datentyp ! Dafür ist es da! –

Antwort

3

Alle Ihre Elemente haben Namensräume definiert. Sie müssen sie deklarieren und entsprechend den Definitionen angeben

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

Mit seltsamen Namespaces wie in diesem Fall würde ich eher vorschlagen, sie überhaupt zu maskieren ... – Shnugo

1

Sie haben Namespaces vergessen, die mit dem Attribut xmlns deklariert wurden. Schauen Sie sich folgendes Beispiel:

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

Mit seltsamen Namespaces wie in diesem Fall würde ich eher vorschlagen, sie zu maskieren ... – Shnugo

1

jedoch diese XML erzeugt wird, werden die Namespaces ziemlich seltsam ... Sie haben die gleichen Namensraum immer und immer erklärt ... Wenn ich das falsch nicht, die Namespaces es sollte nicht wirklich die Art und Weise sind sein, deshalb würde ich sie ignorieren:

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] 

auf jeden Fall würde ich Ihnen raten, die Namensräume innerhalb eines WITH XMLNAMESPACE zu erklären, anstatt innerhalb der .value -function. Wenn Sie jemals aus dieser mehr als einen Wert benötigen, können Sie viel besser Erstellen von Abfragen zu lesen:

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: Mit DEFAULT einem Dummy-Namensraum wie top: in anderen Antworten vermeidet ...