XML 생성(XQuery)

적용 대상:SQL Server

XQuery에서는 직접계산 생성자를 사용하여 쿼리 내에서 XML 구조를 생성할 수 있습니다.

참고 항목

직접 생성자와 계산된 생성자 간에는 차이가 없습니다.

직접 생성자 사용

직접 생성자를 사용하는 경우 XML을 생성할 때 XML과 유사한 구문을 지정합니다. 다음 예제에서는 직접 생성자에 의한 XML 생성을 보여 줍니다.

요소 생성

XML 표기를 사용할 때 요소를 생성할 수 있습니다. 다음 예제에서는 직접 요소 생성자 식을 사용하고 ProductModel> 요소를 만듭니다<. 생성된 요소에는 3개의 자식 요소가 있습니다.

  • 텍스트 노드입니다.

  • 요약 및 <기능>의 <> 두 요소 노드입니다.

    • <Summary> 요소에는 값이 "일부 설명"인 하나의 텍스트 노드 자식이 있습니다.

    • Features 요소에는 Color>, <Weight> 및 <Warranty의 <세 가지 요소 노드 자식이 있습니다>.>< 이러한 각 노드에는 하나의 텍스트 노드 자식이 있으며 각각 Red, 25, 2년 부분 및 노동 값이 있습니다.

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

결과 XML은 다음과 같습니다.

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

이 예제와 같이 상수 식에서 요소를 생성하는 것이 유용하지만 이 XQuery 언어 기능의 진정한 기능은 데이터베이스에서 데이터를 동적으로 추출하는 XML을 생성하는 기능입니다. 중괄호를 사용하여 쿼리 식을 지정할 수 있습니다. 결과 XML에서 식은 해당 값으로 대체됩니다. 예를 들어 다음 쿼리는 하나의 자식 요소(>e<)를 사용하여 <NewRoot> 요소를 생성합니다. 요소 <e> 값은 중괄호 안에 경로 식을 지정하여 계산됩니다("{ ... }").

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

중괄호는 컨텍스트 전환 토큰 역할을 하며 쿼리를 XML 생성에서 쿼리 평가로 전환합니다. 이 경우 중괄호 /root안의 XQuery 경로 식이 계산되고 결과가 대체됩니다.

결과는 다음과 같습니다.

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

다음 쿼리는 이전 쿼리와 비슷합니다. 그러나 중괄호의 식은 요소의 <>root원자성 값을 검색하는 data() 함수를 지정하고 생성된 요소<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;  

결과는 다음과 같습니다.

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

컨텍스트 전환 토큰 대신 텍스트의 일부로 중괄호를 사용하려는 경우 이 예제와 같이 "}}" 또는 "{{"로 이스케이프할 수 있습니다.

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;  

결과는 다음과 같습니다.

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

다음 쿼리는 직접 요소 생성자를 사용하여 요소를 생성하는 또 다른 예입니다. 또한 중괄호에서 <FirstLocation> 식을 실행하여 요소의 값을 가져옵니다. 쿼리 식은 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;  

결과는 다음과 같습니다.

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

XML 생성의 요소 콘텐츠

다음 예제에서는 직접 요소 생성자를 사용 하 여 요소 콘텐츠를 생성 하는 식의 동작을 보여 줍니다. 다음 예제에서 직접 요소 생성자는 하나의 식을 지정합니다. 이 식의 경우 결과 XML에 하나의 텍스트 노드가 만들어집니다.

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>');  
  

식 계산에서 생성된 원자성 값 시퀀스는 결과와 같이 인접한 원자 값 사이에 공백이 추가된 텍스트 노드에 추가됩니다. 생성된 요소에는 하나의 자식이 있습니다. 결과에 표시된 값을 포함하는 텍스트 노드입니다.

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

하나의 식 대신 세 개의 텍스트 노드를 생성하는 세 개의 별도 식을 지정하면 인접한 텍스트 노드가 연결하여 결과 XML에서 단일 텍스트 노드로 병합됩니다.

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>');  

생성된 요소 노드에는 하나의 자식이 있습니다. 결과에 표시된 값을 포함하는 텍스트 노드입니다.

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

특성 생성

직접 요소 생성자를 사용하여 요소를 생성하는 경우 이 예제와 같이 XML과 유사한 구문을 사용하여 요소의 특성을 지정할 수도 있습니다.

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

결과 XML은 다음과 같습니다.

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

생성된 요소 <ProductModel> 에는 ProductModelID 특성과 이러한 자식 노드가 있습니다.

  • 텍스트 노드 This is product model catalog description.

  • 요소 노드입니다 <Summary>. 이 노드에는 하나의 텍스트 노드 자식이 있습니다 Some description.

특성을 생성할 때 중괄호로 식을 사용하여 해당 값을 지정할 수 있습니다. 이 경우 식의 결과가 특성 값으로 반환됩니다.

다음 예제 에서는 data() 함수가 반드시 필요한 것은 아닙니다. 식 값을 특성 에 할당하기 때문에 data() 는 지정된 식의 형식화된 값을 검색하기 위해 암시적으로 적용됩니다.

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

결과는 다음과 같습니다.

<NewRoot attr="5" />  

다음은 LocationID 및 SetupHrs 특성 생성에 대해 식을 지정하는 또 다른 예입니다. 이러한 식은 명령 열의 XML에 대해 평가됩니다. 식의 형식화된 값이 특성에 할당됩니다.

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;  

다음은 부분 결과입니다.

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

구현 제한 사항

제한 사항은 다음과 같습니다.

  • 다중 또는 혼합(문자열 및 XQuery 식) 특성 식은 지원되지 않습니다. 예를 들어 다음 쿼리와 같이 상수인 XML Item 을 생성하고 쿼리 식을 평가하여 값을 5 가져옵니다.

    <a attr="Item 5" />  
    

    다음 쿼리는 상수 문자열을 식({/x})과 혼합하고 지원되지 않으므로 오류를 반환합니다.

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

    이 경우에 다음과 같은 옵션을 사용할 수 있습니다.

    • 원자성 값 두 개를 연결하여 특성 값을 만듭니다. 이러한 원자성 값은 원자성 값 사이의 공백을 사용하여 특성 값으로 직렬화됩니다.

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

      결과는 다음과 같습니다.

      <a attr="Item 5" />  
      
    • concat 함수사용하여 두 문자열 인수를 결과 특성 값에 연결합니다.

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

      이 경우 두 문자열 값 사이에 공백이 추가되지 않습니다. 두 값 사이에 공백을 지정하려면 명시적으로 제공해야 합니다.

      결과는 다음과 같습니다.

      <a attr="Item5" />  
      
  • 여러 개의 식을 특성 값으로 사용할 수 없습니다. 예를 들어 다음 쿼리는 오류를 반환합니다.

    DECLARE @x xml  
    SET @x ='<x>5</x>'  
    SELECT @x.query( '<a attr="{/x}{/x}"/>' )  
    
  • 다른 유형의 시퀀스는 지원되지 않습니다. 다음 예와 같이 다른 유형의 시퀀스를 특성 값으로 할당하면 오류가 반환됩니다. 이 예제에서는 다른 유형의 시퀀스, 문자열 "Item" 및 요소가 <x>특성 값으로 지정됩니다.

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

    data() 함수를 적용하는 경우 쿼리는 문자열과 연결된 식/x의 원자성 값을 검색하기 때문에 작동합니다. 다음은 원자성 값의 시퀀스입니다.

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

    결과는 다음과 같습니다.

    <a attr="Item 5" />  
    
  • 특성 노드 순서는 정적 형식 검사 중에가 아니라 serialization 중에 적용됩니다. 예를 들어 다음 쿼리는 특성 노드가 아닌 노드 뒤에 특성을 추가하려고 시도하기 때문에 실패합니다.

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

    위의 쿼리는 다음 오류를 반환합니다.

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

네임스페이스 추가

직접 생성자를 사용하여 XML을 생성하면 네임스페이스 접두사를 사용하여 생성된 요소와 특성 이름을 한정할 수 있습니다. 다음과 같은 방법으로 접두사를 네임스페이스에 바인딩할 수 있습니다.

  • 네임스페이스 선언 특성을 사용합니다.

  • WITH XMLNAMESPACES 절을 사용합니다.

  • XQuery 프롤로그에서 바인딩

네임스페이스 선언 특성을 사용하여 네임스페이스 추가

다음 예제에서는 요소 <a> 생성 시 네임스페이스 선언 특성을 사용하여 기본 네임스페이스를 선언합니다. 자식 요소의 생성은 부모 요소 <b> 에 선언된 기본 네임스페이스의 선언을 실행 취소합니다.

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

결과는 다음과 같습니다.

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

네임스페이스에 접두사를 할당할 수 있습니다. 접두사는 요소 <a>생성에 지정됩니다.

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

결과는 다음과 같습니다.

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

XML 생성에서 기본 네임스페이스를 선언 해제할 수 있지만 네임스페이스 접두사를 선언 취소할 수는 없습니다. 다음 쿼리는 요소 <b>생성에 지정된 대로 접두사를 선언 해제할 수 없으므로 오류를 반환합니다.

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

새로 생성된 네임스페이스는 쿼리 안에서 사용할 수 있습니다. 예를 들어 다음 쿼리는 요소를 <FirstLocation>생성할 때 네임스페이스를 선언하고 LocationID 및 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  

이러한 방식으로 새 네임스페이스 접두사를 만들면 이 접두사에 대한 기존 네임스페이스 선언이 재정의됩니다. 예를 들어 쿼리 프롤로그의 네임스페이스 선언 AWMI="https://someURI"은 요소의 네임스페이스 선언에 의해 재정의 <FirstLocation> 됩니다.

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  

프롤로그를 사용하여 네임스페이스 추가

이 예제에서는 네임스페이스를 생성된 XML에 추가하는 방법을 보여 줍니다. 기본 네임스페이스는 쿼리 프롤로그에 선언됩니다.

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

요소 <b>생성 시 네임스페이스 선언 특성은 빈 문자열을 해당 값으로 지정합니다. 그러면 부모에 선언된 기본 네임스페이스를 선언하지 않습니다.

결과는 다음과 같습니다.

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

XML 생성 및 공백 처리

XML 생성의 요소 콘텐츠에는 공백 문자가 포함될 수 있습니다. 이러한 문자는 다음 방법으로 처리됩니다.

  • 네임스페이스 URI의 공백 문자는 XSD 형식 anyURI로 처리됩니다. 특히 다음과 같이 처리됩니다.

    • 시작 및 끝의 공백 문자는 모두 잘립니다.

    • 내부 공백 문자 값이 단일 공백으로 축소됨

  • 특성 콘텐츠 내의 줄 바꿈 문자는 공백으로 대체됩니다. 다른 모든 공백 문자는 그대로 유지됩니다.

  • 요소 내의 공백은 유지됩니다.

다음 예제에서는 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  
  

결과는 다음과 같습니다.

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

기타 직접 XML 생성자

명령 및 XML 주석 처리를 위한 생성자는 해당 XML 구문과 동일한 구문을 사용합니다. 텍스트 노드에 대한 계산 생성자도 지원되지만 주로 XML DML에서 텍스트 노드를 생성하는 데 사용됩니다.

참고 명시적 텍스트 노드 생성자를 사용하는 예제는 삽입의 특정 예제 (XML DML)를 참조하세요.

다음 쿼리에서 생성된 XML에는 요소, 특성 두 개, 주석 및 처리 명령이 포함됩니다. 시퀀스가 생성되기 때문에 쉼표는 앞에 <FirstLocation>사용됩니다.

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;  
  

다음은 부분 결과입니다.

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

계산 생성자 사용

. 이 경우 생성하려는 노드 유형을 식별하는 키워드를 지정합니다. 다음 키워드만 지원됩니다.

  • 요소

  • 특성

  • text

요소 및 특성 노드의 경우 이러한 키워드 뒤에 노드 이름과 중괄호로 묶인 식이 해당 노드에 대한 콘텐츠를 생성합니다. 다음 예에서는 이 XML을 생성합니다.

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

계산된 생성자를 사용하여 XML을 생성하는 쿼리입니다.

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

노드 콘텐츠를 생성하는 식은 쿼리 식을 지정할 수 있습니다.

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 }  
 }  
               } ')  

XQuery 사양에 정의된 대로 계산된 요소 및 특성 생성자를 사용하여 노드 이름을 계산할 수 있습니다. SQL Server에서 직접 생성자를 사용하는 경우 요소 및 특성과 같은 노드 이름을 상수 리터럴로 지정해야 합니다. 따라서 요소 및 특성에 대한 직접 생성자와 계산된 생성자에는 차이가 없습니다.

다음 예제에서는 ProductModel 테이블에 있는 xml 데이터 형식의 지침 열에 저장된 XML 제조 지침에서 생성된 노드의 콘텐츠를 가져옵니다.

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  

다음은 부분 결과입니다.

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

추가 구현 제한 사항

계산된 특성 생성자는 새 네임스페이스를 선언하는 데 사용할 수 없습니다. 또한 다음 계산 생성자는 SQL Server에서 지원되지 않습니다.

  • 계산된 문서 노드 생성자

  • 계산된 처리 명령 생성자

  • 계산된 주석 생성자

참고 항목

XQuery 식