Menambahkan namespace ke kueri menggunakan WITH XMLNAMESPACES

Berlaku untuk:SQL ServerAzure SQL DatabaseAzure SQL Managed Instance

WITH XMLNAMESPACES (Transact-SQL) menyediakan dukungan URI namespace dengan cara berikut:

  • Ini membuat awalan namespace layanan untuk pemetaan URI tersedia saat Membuat XML Menggunakan kueri XML .

  • Ini membuat namespace layanan untuk pemetaan URI tersedia untuk konteks namespace statis dari Metode Jenis Data xml.

Gunakan DENGAN XMLNAMESPACES dalam UNTUK kueri XML

DENGAN XMLNAMESPACES memungkinkan Anda menyertakan namespace XML dalam untuk kueri XML. Misalnya, pertimbangkan kueri XML FOR berikut:

SELECT ProductID, Name, Color
FROM   Production.Product
WHERE  ProductID IN (316, 317)
FOR XML RAW;

Ini adalah hasilnya:

<row ProductID="316" Name="Blade" />
<row ProductID="317" Name="LL Crankarm" Color="Black" />

Untuk menambahkan namespace ke XML yang dibangun oleh kueri FOR XML, pertama-tama tentukan awalan namespace layanan ke pemetaan URI dengan menggunakan klausa WITH NAMESPACES. Kemudian, gunakan awalan namespace dalam menentukan nama dalam kueri seperti yang diperlihatkan dalam kueri yang dimodifikasi berikut ini. Klausa WITH XMLNAMESPACES menentukan awalan namespace (ns1) ke pemetaan URI (uri). ns1 Awalan kemudian digunakan dalam menentukan elemen dan nama atribut yang akan dibangun oleh kueri FOR XML.

WITH XMLNAMESPACES ('uri' as ns1)
SELECT ProductID as 'ns1:ProductID',
       Name      as 'ns1:Name',
       Color     as 'ns1:Color'
FROM  Production.Product
WHERE ProductID IN (316, 317)
FOR XML RAW ('ns1:Prod'), ELEMENTS;

Hasil XML menyertakan awalan namespace:

<ns1:Prod xmlns:ns1="uri">
  <ns1:ProductID>316</ns1:ProductID>
  <ns1:Name>Blade</ns1:Name>
</ns1:Prod>
<ns1:Prod xmlns:ns1="uri">
  <ns1:ProductID>317</ns1:ProductID>
  <ns1:Name>LL Crankarm</ns1:Name>
  <ns1:Color>Black</ns1:Color>
</ns1:Prod>

Berikut ini berlaku untuk klausa WITH XMLNAMESPACES:

  • Ini hanya didukung pada mode RAW, AUTO, dan PATH dari kueri FOR XML. Mode EKSPLISIT tidak didukung.

  • Ini hanya memengaruhi awalan namespace kueri FOR XML dan metode jenis data xml , tetapi bukan pengurai XML. Misalnya, kueri berikut mengembalikan kesalahan, karena dokumen XML tidak memiliki deklarasi namespace untuk awalan myNS.

  • Direktif FOR XML, XMLSCHEMA, dan XMLDATA tidak dapat digunakan saat klausul WITH XMLNAMESPACES sedang digunakan.

    CREATE TABLE T (x xml);
    GO
    WITH XMLNAMESPACES ('https://abc' as myNS )
    INSERT INTO T VALUES('<myNS:root/>');
    GO
    

Gunakan direktif XSINIL

Anda tidak dapat menentukan awalan xsi dalam klausul WITH XMLNAMESPACES jika Anda menggunakan arahan ELEMENTS XSINIL. Sebagai gantinya, ini ditambahkan secara otomatis saat Anda menggunakan ELEMENTS XSINIL. Kueri berikut menggunakan ELEMENTS XSINIL yang menghasilkan XML yang berpusat pada elemen tempat nilai null dipetakan ke elemen yang memiliki atribut xsi:nil yang diatur ke True.

WITH XMLNAMESPACES ('uri' as ns1)
SELECT ProductID as 'ns1:ProductID',
       Name      as 'ns1:Name',
       Color     as 'ns1:Color'
FROM Production.Product
WHERE ProductID = 316
FOR XML RAW, ELEMENTS XSINIL;

Ini adalah hasilnya:

<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns1="uri">
  <ns1:ProductID>316</ns1:ProductID>
  <ns1:Name>Blade</ns1:Name>
  <ns1:Color xsi:nil="true" />
</row>

Tentukan namespace default

Alih-alih mendeklarasikan awalan namespace, Anda dapat mendeklarasikan namespace default dengan menggunakan kata kunci DEFAULT. Dalam kueri FOR XML, kueri akan mengikat namespace default ke simpul XML dalam XML yang dihasilkan. Dalam contoh berikut, WITH XMLNAMESPACES menentukan dua awalan namespace yang ditentukan bersama dengan namespace default.

WITH XMLNAMESPACES ('uri1' as ns1,
                    'uri2' as ns2,
                    DEFAULT 'uri2')
SELECT ProductID,
      Name,
      Color
FROM Production.Product
WHERE ProductID IN (316, 317)
FOR XML RAW ('ns1:Product'), ROOT('ns2:root'), ELEMENTS;

Kueri FOR XML menghasilkan XML yang berentrik elemen. Kueri menggunakan awalan namespace layanan dalam node penamaan. Dalam klausa SELECT, ProductID, Name, dan Color tidak menentukan nama dengan awalan apa pun. Oleh karena itu, elemen yang sesuai dalam XML yang dihasilkan milik namespace default.

<ns2:root xmlns="uri2" xmlns:ns2="uri2" xmlns:ns1="uri1">
  <ns1:Product>
    <ProductID>316</ProductID>
    <Name>Blade</Name>
  </ns1:Product>
  <ns1:Product>
    <ProductID>317</ProductID>
    <Name>LL Crankarm</Name>
    <Color>Black</Color>
  </ns1:Product>
</ns2:root>

Kueri berikut mirip dengan yang sebelumnya, kecuali bahwa mode FOR XML AUTO ditentukan.

WITH XMLNAMESPACES ('uri1' as ns1,  'uri2' as ns2,DEFAULT 'uri2')
SELECT ProductID,
      Name,
      Color
FROM Production.Product as "ns1:Product"
WHERE ProductID IN (316, 317)
FOR XML AUTO, ROOT('ns2:root'), ELEMENTS;

Menggunakan namespace yang telah ditentukan sebelumnya

Saat Anda menggunakan namespace yang telah ditentukan sebelumnya, kecuali namespace xml dan namespace xsi saat ELEMENTS XSINIL digunakan, Anda harus secara eksplisit menentukan pengikatan namespace dengan menggunakan XMLNAMESPACES. Kueri berikut secara eksplisit menentukan awalan namespace layanan ke pengikatan URI untuk namespace yang telah ditentukan sebelumnya (urn:schemas-microsoft-com:xml-sql).

WITH XMLNAMESPACES ('urn:schemas-microsoft-com:xml-sql' as sql)
SELECT 'SELECT * FROM Customers FOR XML AUTO, ROOT("a")' AS "sql:query"
FOR XML PATH('sql:root');

Ini adalah hasilnya. Pengguna SQLXML terbiasa dengan templat XML ini. Untuk informasi selengkapnya, lihat Konsep Pemrograman SQLXML 4.0.

<sql:root xmlns:sql="urn:schemas-microsoft-com:xml-sql">
  <sql:query>SELECT * FROM Customers FOR XML AUTO, ROOT("a")</sql:query>
</sql:root>

Hanya awalan namespace xml yang dapat digunakan tanpa secara eksplisit menentukannya di WITH XMLNAMESPACES, seperti yang diperlihatkan dalam kueri mode PATH berikut. Selain itu, jika awalan dideklarasikan, prefiks harus terikat ke namespace http://www.w3.org/XML/1998/namespace. Nama yang ditentukan dalam klausa SELECT merujuk ke awalan namespace xml yang tidak ditentukan secara eksplisit dengan menggunakan WITH XMLNAMESPACES.

SELECT 'en'    as "English/@xml:lang",
       'food'  as "English",
       'ger'   as "German/@xml:lang",
       'Essen' as "German"
FOR XML PATH ('Translation');
GO

Atribut @xml:lang menggunakan namespace xml yang telah ditentukan sebelumnya. Karena XML versi 1.0 tidak memerlukan deklarasi eksplisit pengikatan namespace xml, hasilnya tidak akan menyertakan deklarasi eksplisit pengikatan namespace.

Ini adalah hasilnya:

<Translation>
  <English xml:lang="en">food</English>
  <German xml:lang="ger">Essen</German>
</Translation>

Menggunakan WITH XMLNAMESPACES dengan metode tipe data xml

Metode Tipe Data xml yang ditentukan dalam kueri SELECT, atau di UPDATE saat metodenyamodify(), semua harus mengulangi deklarasi namespace dalam prolog mereka. Ini bisa memakan waktu. Misalnya, kueri berikut mengambil ID model produk yang deskripsi katalognya menyertakan spesifikasi. Artinya, <Specifications> elemen ada.

SELECT ProductModelID, CatalogDescription.query('
declare namespace pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
    <Product
        ProductModelID= "{ sql:column("ProductModelID") }"
        />
') AS Result
FROM Production.ProductModel
WHERE CatalogDescription.exist('
    declare namespace  pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
     /pd:ProductDescription[(pd:Specifications)]'
    ) = 1;

Dalam kueri sebelumnya, metode query() dan exist() mendeklarasikan namespace yang sama dalam prolog mereka. Contohnya:

declare namespace pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";

Atau, Anda dapat mendeklarasikan WITH XMLNAMESPACES terlebih dahulu dan menggunakan awalan namespace dalam kueri. Dalam hal ini, query() metode dan exist() tidak perlu menyertakan deklarasi namespace dalam prolog mereka.

WITH XMLNAMESPACES ('https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription' as pd)
SELECT ProductModelID, CatalogDescription.query('
    <Product
        ProductModelID= "{ sql:column("ProductModelID") }"
        />
') AS Result
FROM Production.ProductModel
WHERE CatalogDescription.exist('
     /pd:ProductDescription[(pd:Specifications)]'
    ) = 1;
GO

Deklarasi eksplisit dalam prolog XQuery menggantikan awalan namespace dan namespace elemen default yang ditentukan dalam klausul WITH.

Baca juga