Konstruksi XML (XQuery)

Berlaku untuk:SQL Server

Di XQuery, Anda dapat menggunakan konstruktor langsung dan komputasi untuk membuat struktur XML dalam kueri.

Catatan

Tidak ada perbedaan antara konstruktor langsung dan komputasi .

Menggunakan Konstruktor Langsung

Saat Anda menggunakan konstruktor langsung, Anda menentukan sintaks seperti XML saat membuat XML. Contoh berikut mengilustrasikan konstruksi XML oleh konstruktor langsung.

Membangun Elemen

Dalam menggunakan notasi XML, Anda dapat membuat elemen. Contoh berikut menggunakan ekspresi konstruktor elemen langsung dan membuat <elemen ProductModel> . Elemen yang dibangun memiliki tiga elemen turunan

  • Simpul teks.

  • Dua node elemen, <Ringkasan> dan <Fitur>.

    • Elemen <Ringkasan> memiliki satu anak simpul teks yang nilainya adalah "Beberapa deskripsi".

    • Elemen <Fitur> memiliki tiga elemen node children, <Color>, <Weight>, dan <Warranty>. Masing-masing simpul ini memiliki satu anak simpul teks dan memiliki nilai masing-masing bagian dan tenaga kerja Merah, 25, 2 tahun.

declare @x xml;  
set @x='';  
select @x.query('<ProductModel ProductModelID="111">;  
This is product model catalog description.  
<Summary>Some description</Summary>  
<Features>  
  <Color>Red</Color>  
  <Weight>25</Weight>  
  <Warranty>2 years parts and labor</Warranty>  
</Features></ProductModel>')  
  

Ini adalah XML yang dihasilkan:

<ProductModel ProductModelID="111">  
  This is product model catalog description.  
  <Summary>Some description</Summary>  
  <Features>  
    <Color>Red</Color>  
    <Weight>25</Weight>  
    <Warranty>2 years parts and labor</Warranty>  
  </Features>  
</ProductModel>  

Meskipun membangun elemen dari ekspresi konstan, seperti yang ditunjukkan dalam contoh ini, berguna, kekuatan sebenarnya dari fitur bahasa XQuery ini adalah kemampuan untuk membangun XML yang secara dinamis mengekstrak data dari database. Anda bisa menggunakan kurung kurawal untuk menentukan ekspresi kueri. Dalam XML yang dihasilkan, ekspresi digantikan oleh nilainya. Misalnya, kueri berikut membuat <NewRoot> elemen dengan satu elemen anak ().<e> Nilai elemen <e> dihitung dengan menentukan ekspresi jalur di dalam kurung kurawal ("{ ... }").

DECLARE @x xml;  
SET @x='<root>5</root>';  
SELECT @x.query('<NewRoot><e> { /root } </e></NewRoot>');  

Kurung kurawal bertindak sebagai token peralihan konteks dan mengalihkan kueri dari konstruksi XML ke evaluasi kueri. Dalam hal ini, ekspresi jalur XQuery di dalam kurung kurawal, /root, dievaluasi dan hasilnya diganti.

Ini adalah hasilnya:

<NewRoot>  
  <e>  
    <root>5</root>  
  </e>  
</NewRoot>  

Kueri berikut ini mirip dengan kueri sebelumnya. Namun, ekspresi dalam kurung kurawal menentukan fungsi data() untuk mengambil nilai>root< atom elemen dan menetapkannya ke elemen yang dibangun, . <e>

DECLARE @x xml;  
SET @x='<root>5</root>';  
DECLARE @y xml;  
SET @y = (SELECT @x.query('  
                           <NewRoot>  
                             <e> { data(/root) } </e>  
                           </NewRoot>' ));  
SELECT @y;  

Ini adalah hasilnya:

<NewRoot>  
  <e>5</e>  
</NewRoot>  

Jika Anda ingin menggunakan kurung kurawal sebagai bagian dari teks Anda alih-alih token peralihan konteks, Anda dapat melepaskannya sebagai "}}" atau "{{", seperti yang ditunjukkan dalam contoh ini:

DECLARE @x xml;  
SET @x='<root>5</root>';  
DECLARE @y xml;  
SET @y = (SELECT @x.query('  
<NewRoot> Hello, I can use {{ and  }} as part of my text</NewRoot>'));  
SELECT @y;  

Ini adalah hasilnya:

<NewRoot> Hello, I can use { and  } as part of my text</NewRoot>  

Kueri berikut adalah contoh lain dari membangun elemen dengan menggunakan konstruktor elemen langsung. Selain itu, nilai <FirstLocation> elemen diperoleh dengan mengeksekusi ekspresi dalam kurung kurawal. Ekspresi kueri mengembalikan langkah-langkah manufaktur di lokasi pusat kerja pertama dari kolom Instruksi tabel Production.ProductModel.

SELECT Instructions.query('  
    declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";  
        <FirstLocation>  
           { /AWMI:root/AWMI:Location[1]/AWMI:step }  
        </FirstLocation>   
') as Result   
FROM Production.ProductModel  
WHERE ProductModelID=7;  

Ini adalah hasilnya:

<FirstLocation>  
  <AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">  
      Insert <AWMI:material>aluminum sheet MS-2341</AWMI:material> into the <AWMI:tool>T-85A framing tool</AWMI:tool>.   
  </AWMI:step>  
  <AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">  
      Attach <AWMI:tool>Trim Jig TJ-26</AWMI:tool> to the upper and lower right corners of the aluminum sheet.   
  </AWMI:step>  
   ...  
</FirstLocation>  

Konten Elemen dalam Konstruksi XML

Contoh berikut mengilustrasikan perilaku ekspresi dalam membangun konten elemen dengan menggunakan konstruktor elemen langsung. Dalam contoh berikut, konstruktor elemen langsung menentukan satu ekspresi. Untuk ekspresi ini, satu simpul teks dibuat dalam XML yang dihasilkan.

declare @x xml;  
set @x='  
<root>  
  <step>This is step 1</step>  
  <step>This is step 2</step>  
  <step>This is step 3</step>  
</root>';  
select @x.query('  
<result>  
 { for $i in /root[1]/step  
    return string($i)  
 }  
</result>');  
  

Urutan nilai atom yang dihasilkan dari evaluasi ekspresi ditambahkan ke simpul teks dengan spasi yang ditambahkan di antara nilai atomik yang berdekatan, seperti yang ditunjukkan pada hasilnya. Elemen yang dibangun memiliki satu anak. Ini adalah simpul teks yang berisi nilai yang diperlihatkan dalam hasilnya.

<result>This is step 1 This is step 2 This is step 3</result>  

Alih-alih satu ekspresi, jika Anda menentukan tiga ekspresi terpisah yang menghasilkan tiga simpul teks, simpul teks yang berdekatan digabungkan ke dalam satu simpul teks, dengan penggabungan, dalam XML yang dihasilkan.

declare @x xml;  
set @x='  
<root>  
  <step>This is step 1</step>  
  <step>This is step 2</step>  
  <step>This is step 3</step>  
</root>';  
select @x.query('  
<result>  
 { string(/root[1]/step[1]) }  
 { string(/root[1]/step[2]) }  
 { string(/root[1]/step[3]) }  
</result>');  

Node elemen yang dibangun memiliki satu anak. Ini adalah simpul teks yang berisi nilai yang diperlihatkan dalam hasilnya.

<result>This is step 1This is step 2This is step 3</result>  

Membuat Atribut

Saat Anda membuat elemen dengan menggunakan konstruktor elemen langsung, Anda juga dapat menentukan atribut elemen dengan menggunakan sintaks seperti XML, seperti yang ditunjukkan dalam contoh ini:

declare @x xml;  
set @x='';  
select @x.query('<ProductModel ProductModelID="111">;  
This is product model catalog description.  
<Summary>Some description</Summary>  
</ProductModel>')  

Ini adalah XML yang dihasilkan:

<ProductModel ProductModelID="111">  
  This is product model catalog description.  
  <Summary>Some description</Summary>  
</ProductModel>  

Elemen <ProductModel> yang dibangun memiliki atribut ProductModelID dan node anak ini:

  • Simpul teks, This is product model catalog description.

  • Node elemen, <Summary>. Simpul ini memiliki satu anak simpul teks, Some description.

Saat membuat atribut, Anda dapat menentukan nilainya dengan ekspresi dalam kurung kurawal. Dalam hal ini, hasil ekspresi dikembalikan sebagai nilai atribut.

Dalam contoh berikut, fungsi data() tidak benar-benar diperlukan. Karena Anda menetapkan nilai ekspresi ke atribut, data() secara implisit diterapkan untuk mengambil nilai ekspresi yang ditentukan.

DECLARE @x xml;  
SET @x='<root>5</root>';  
DECLARE @y xml;  
SET @y = (SELECT @x.query('<NewRoot attr="{ data(/root) }" ></NewRoot>'));  
SELECT @y;  

Ini adalah hasilnya:

<NewRoot attr="5" />  

Berikut ini adalah contoh lain di mana ekspresi ditentukan untuk konstruksi atribut LocationID dan SetupHrs. Ekspresi ini dievaluasi terhadap XML di kolom Instruksi. Nilai ekspresi yang ditik ditetapkan ke atribut .

SELECT Instructions.query('  
    declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";  
        <FirstLocation   
         LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"  
         SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >  
           { /AWMI:root/AWMI:Location[1]/AWMI:step }  
        </FirstLocation>   
') as Result   
FROM  Production.ProductModel  
where ProductModelID=7;  

Ini adalah hasil parsial:

<FirstLocation LocationID="10" SetupHours="0.5" >  
  <AWMI:step ...   
  </AWMI:step>  
  ...  
</FirstLocation>  

Batasan Implementasi

Ini adalah batasannya:

  • Ekspresi atribut beberapa atau campuran (string dan ekspresi XQuery) tidak didukung. Misalnya, seperti yang diperlihatkan dalam kueri berikut, Anda membuat XML di mana Item adalah konstanta dan nilai 5 diperoleh dengan mengevaluasi ekspresi kueri:

    <a attr="Item 5" />  
    

    Kueri berikut mengembalikan kesalahan, karena Anda mencampur string konstanta dengan ekspresi ({/x}) dan ini tidak didukung:

    DECLARE @x xml  
    SET @x ='<x>5</x>'  
    SELECT @x.query( '<a attr="Item {/x}"/>' )   
    

    Dalam hal ini, Anda memiliki opsi berikut:

    • Bentuk nilai atribut berdasarkan perangkaian dua nilai atomik. Nilai atom ini diserialisasikan ke dalam nilai atribut dengan spasi antara nilai atom:

      SELECT @x.query( '<a attr="{''Item'', data(/x)}"/>' )   
      

      Ini adalah hasilnya:

      <a attr="Item 5" />  
      
    • Gunakan fungsi concat untuk menggabungkan dua argumen string ke dalam nilai atribut yang dihasilkan:

      SELECT @x.query( '<a attr="{concat(''Item'', /x[1])}"/>' )   
      

      Dalam hal ini, tidak ada spasi yang ditambahkan di antara dua nilai string. Jika Anda menginginkan spasi di antara dua nilai, Anda harus secara eksplisit menyediakannya.

      Ini adalah hasilnya:

      <a attr="Item5" />  
      
  • Beberapa ekspresi sebagai nilai atribut tidak didukung. Misalnya, kueri berikut mengembalikan kesalahan:

    DECLARE @x xml  
    SET @x ='<x>5</x>'  
    SELECT @x.query( '<a attr="{/x}{/x}"/>' )  
    
  • Urutan heterogen tidak didukung. Setiap upaya untuk menetapkan urutan heterogen sebagai nilai atribut akan mengembalikan kesalahan, seperti yang ditunjukkan dalam contoh berikut. Dalam contoh ini, urutan heterogen, string "Item" dan elemen <x>, ditentukan sebagai nilai atribut:

    DECLARE @x xml  
    SET @x ='<x>5</x>'  
    select @x.query( '<a attr="{''Item'', /x }" />')  
    

    Jika Anda menerapkan fungsi data(), kueri berfungsi karena mengambil nilai atom ekspresi, /x, yang digabungkan dengan string. Berikut ini adalah urutan nilai atom:

    SELECT @x.query( '<a attr="{''Item'', data(/x)}"/>' )   
    

    Ini adalah hasilnya:

    <a attr="Item 5" />  
    
  • Urutan node atribut diberlakukan selama serialisasi daripada selama pemeriksaan jenis statis. Misalnya, kueri berikut gagal karena mencoba menambahkan atribut setelah node non-atribut.

    select convert(xml, '').query('  
    element x { attribute att { "pass" }, element y { "Element text" }, attribute att2 { "fail" } }  
    ')  
    go  
    

    Kueri di atas mengembalikan kesalahan berikut:

    XML well-formedness check: Attribute cannot appear outside of element declaration. Rewrite your XQuery so it returns well-formed XML.  
    

Menambahkan Namespace Layanan

Saat membuat XML dengan menggunakan konstruktor langsung, elemen dan nama atribut yang dibangun dapat dikualifikasi dengan menggunakan awalan namespace layanan. Anda dapat mengikat awalan ke namespace layanan dengan cara berikut:

  • Dengan menggunakan atribut deklarasi namespace.

  • Dengan menggunakan klausa WITH XMLNAMESPACES.

  • Di prolog XQuery.

Menggunakan Atribut Deklarasi Namespace layanan untuk Menambahkan Namespace

Contoh berikut menggunakan atribut deklarasi namespace dalam konstruksi elemen <a> untuk mendeklarasikan namespace default. Konstruksi elemen <b> turunan membatalkan deklarasi namespace default yang dideklarasikan dalam elemen induk.

declare @x xml  
set @x ='<x>5</x>'  
select @x.query( '  
  <a xmlns="a">  
    <b xmlns=""/>  
  </a>' )   

Ini adalah hasilnya:

<a xmlns="a">  
  <b xmlns="" />  
</a>  

Anda dapat menetapkan awalan ke namespace. Awalan ditentukan dalam konstruksi elemen <a>.

declare @x xml  
set @x ='<x>5</x>'  
select @x.query( '  
  <x:a xmlns:x="a">  
    <b/>  
  </x:a>' )  

Ini adalah hasilnya:

<x:a xmlns:x="a">  
  <b />  
</x:a>  

Anda dapat membatalkan deklarasi namespace default dalam konstruksi XML, tetapi Anda tidak dapat membatalkan deklarasi awalan namespace. Kueri berikut mengembalikan kesalahan, karena Anda tidak dapat membatalkan deklarasi awalan seperti yang ditentukan dalam konstruksi elemen <b>.

declare @x xml  
set @x ='<x>5</x>'  
select @x.query( '  
  <x:a xmlns:x="a">  
    <b xmlns:x=""/>  
  </x:a>' )  

Namespace yang baru dibuat tersedia untuk digunakan di dalam kueri. Misalnya, kueri berikut mendeklarasikan namespace dalam membangun elemen, <FirstLocation>, dan menentukan awalan dalam ekspresi untuk nilai atribut LocationID dan SetupHrs.

SELECT Instructions.query('  
        <FirstLocation xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"  
         LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"  
         SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >  
           { /AWMI:root/AWMI:Location[1]/AWMI:step }  
        </FirstLocation>   
') as Result   
FROM  Production.ProductModel  
where ProductModelID=7  

Perhatikan bahwa membuat awalan namespace baru dengan cara ini akan menimpa deklarasi namespace layanan yang sudah ada sebelumnya untuk awalan ini. Misalnya, deklarasi namespace, AWMI="https://someURI", dalam prolog kueri ditimpa oleh deklarasi namespace dalam <FirstLocation> elemen .

SELECT Instructions.query('  
declare namespace AWMI="https://someURI";  
        <FirstLocation xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"  
         LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"  
         SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >  
           { /AWMI:root/AWMI:Location[1]/AWMI:step }  
        </FirstLocation>   
') as Result   
FROM  Production.ProductModel  
where ProductModelID=7  

Menggunakan Prolog untuk Menambahkan Namespace

Contoh ini menggambarkan bagaimana namespace dapat ditambahkan ke XML yang dibangun. Namespace default dideklarasikan dalam prolog kueri.

declare @x xml  
set @x ='<x>5</x>'  
select @x.query( '  
           declare default element namespace "a";  
            <a><b xmlns=""/></a>' )  

Perhatikan bahwa dalam konstruksi elemen <b>, atribut deklarasi namespace ditentukan dengan string kosong sebagai nilainya. Ini membatalkan deklarasi namespace default yang dideklarasikan dalam induk.

Ini adalah hasilnya:

<a xmlns="a">  
  <b xmlns="" />  
</a>  

Konstruksi XML dan Penanganan Ruang Putih

Konten elemen dalam konstruksi XML dapat menyertakan karakter spasi putih. Karakter ini ditangani dengan cara berikut:

  • Karakter spasi putih di URI namespace diperlakukan sebagai jenis XSD anyURI. Secara khusus, ini adalah bagaimana mereka ditangani:

    • Setiap karakter spasi kosong di awal dan akhir dipangkas.

    • Nilai karakter spasi putih internal diciutkan ke dalam satu spasi

  • Karakter linefeed di dalam konten atribut digantikan oleh spasi. Semua karakter spasi putih lainnya tetap seperti adanya.

  • Ruang putih di dalam elemen dipertahankan.

Contoh berikut mengilustrasikan penanganan spasi putih dalam konstruksi XML:

-- line feed is repaced by space.  
declare @x xml  
set @x=''  
select @x.query('  
  
declare namespace myNS="   https://       
 abc/  
xyz  
  
";  
<test attr="    my   
test   attr   
value    " >  
  
<a>  
  
This     is  a  
  
test  
  
</a>  
</test>  
') as XML_Result  
  

Ini adalah hasilnya:

-- result  
<test attr="<test attr="    my test   attr  value    "><a>  
  
This     is  a  
  
test  
  
</a></test>  
"><a>  
  
This     is  a  
  
test  
  
</a></test>  

Konstruktor XML Langsung Lainnya

Konstruktor untuk memproses instruksi dan komentar XML menggunakan sintaks yang sama dengan konstruksi XML yang sesuai. Konstruktor komputasi untuk simpul teks juga didukung, tetapi terutama digunakan dalam XML DML untuk membuat simpul teks.

Catatan Untuk contoh penggunaan konstruktor simpul teks eksplisit, lihat contoh tertentu di sisipkan (XML DML).

Dalam kueri berikut, XML yang dibuat menyertakan elemen, dua atribut, komentar, dan instruksi pemrosesan. Perhatikan bahwa koma digunakan sebelum <FirstLocation>, karena urutan sedang dibangun.

SELECT Instructions.query('  
  declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";  
   <?myProcessingInstr abc="value" ?>,   
   <FirstLocation   
        WorkCtrID = "{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"  
        SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >  
       <!-- some comment -->  
       <?myPI some processing instructions ?>  
       { (/AWMI:root/AWMI:Location[1]/AWMI:step) }  
    </FirstLocation>   
') as Result   
FROM Production.ProductModel  
where ProductModelID=7;  
  

Ini adalah hasil parsial:

<?myProcessingInstr abc="value" ?>  
<FirstLocation WorkCtrID="10" SetupHrs="0.5">  
  <!-- some comment -->  
  <?myPI some processing instructions ?>  
  <AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">I  
  nsert <AWMI:material>aluminum sheet MS-2341</AWMI:material> into the <AWMI:tool>T-85A framing tool</AWMI:tool>.   
  </AWMI:step>  
    ...  
</FirstLocation>  
  

Menggunakan Konstruktor Komputasi

. Dalam hal ini, Anda menentukan kata kunci yang mengidentifikasi jenis simpul yang ingin Anda buat. Hanya kata kunci berikut yang didukung:

  • elemen

  • atribut

  • text

Untuk node elemen dan atribut, kata kunci ini diikuti dengan nama simpul dan juga oleh ekspresi, diapit kurung kurawal, yang menghasilkan konten untuk simpul tersebut. Dalam contoh berikut, Anda membuat XML ini:

<root>  
  <ProductModel PID="5">Some text <summary>Some Summary</summary></ProductModel>  
</root>  

Ini adalah kueri yang menggunakan konstruktor komputasi menghasilkan XML:

declare @x xml  
set @x=''  
select @x.query('element root   
               {   
                  element ProductModel  
     {  
attribute PID { 5 },  
text{"Some text "},  
    element summary { "Some Summary" }  
 }  
               } ')  
  

Ekspresi yang menghasilkan konten simpul dapat menentukan ekspresi kueri.

declare @x xml  
set @x='<a attr="5"><b>some summary</b></a>'  
select @x.query('element root   
               {   
                  element ProductModel  
     {  
attribute PID { /a/@attr },  
text{"Some text "},  
    element summary { /a/b }  
 }  
               } ')  

Perhatikan bahwa elemen komputasi dan konstruktor atribut, seperti yang didefinisikan dalam spesifikasi XQuery, memungkinkan Anda untuk menghitung nama simpul. Ketika Anda menggunakan konstruktor langsung di SQL Server, nama node, seperti elemen dan atribut, harus ditentukan sebagai literal konstanta. Oleh karena itu, tidak ada perbedaan dalam konstruktor langsung dan konstruktor komputasi untuk elemen dan atribut.

Dalam contoh berikut, konten untuk simpul yang dibuat diperoleh dari instruksi manufaktur XML yang disimpan di kolom Instruksi jenis data xml dalam tabel ProductModel.

SELECT Instructions.query('  
  declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";  
   element FirstLocation   
     {  
        attribute LocationID { (/AWMI:root/AWMI:Location[1]/@LocationID)[1] },  
        element   AllTheSteps { /AWMI:root/AWMI:Location[1]/AWMI:step }  
     }  
') as Result   
FROM  Production.ProductModel  
where ProductModelID=7  

Ini adalah hasil parsial:

<FirstLocation LocationID="10">  
  <AllTheSteps>  
    <AWMI:step> ... </AWMI:step>  
    <AWMI:step> ... </AWMI:step>  
    ...  
  </AllTheSteps>  
</FirstLocation>    

Batasan Implementasi Tambahan

Konstruktor atribut komputasi tidak dapat digunakan untuk mendeklarasikan namespace baru. Selain itu, konstruktor komputasi berikut tidak didukung di SQL Server:

  • Konstruktor simpul dokumen komputasi

  • Konstruktor instruksi pemrosesan komputasi

  • Konstruktor komentar komputasi

Lihat Juga

Ekspresi XQuery