SQL XQuery; Обновить атрибут в набранном XML - PullRequest
0 голосов
/ 25 июня 2018

Я пытаюсь обновить атрибуты в типизированном XML.Я делал это в прошлом, создав XML в нетипизированных объектах, затем установив его в типизированный объект (чтобы избежать проблемы), но я хотел бы знать, как напрямую изменять типизированные данные.

Моя схема:

if exists (select [xml_collection_id]
           from   sys.[xml_schema_collections] as [xsc]
           where  [xsc].name = 'xsc_test_stack'
                  and [xsc].[schema_id] = schema_id(N'chamomile'))
  drop xml schema collection [chamomile].[xsc_test_stack];

go

create xml schema collection [chamomile].[xsc_test_stack] as N'<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:chamomile="https://github.com/KELightsey/chamomile" targetNamespace="https://github.com/KELightsey/chamomile">
  <xsd:element name="test_stack">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="description" type="xsd:string" minOccurs="1" maxOccurs="1" />
        <xsd:element name="test_stack_detail" type="chamomile:any_complex_type" minOccurs="0" maxOccurs="unbounded" />
        <xsd:element name="test" type="chamomile:any_complex_type" minOccurs="0" maxOccurs="unbounded" />
      </xsd:sequence>
      <xsd:attribute name="name" type="xsd:string" use="required" />
      <xsd:attribute name="test_count" type="xsd:int" use="required" />
      <xsd:attribute name="pass_count" type="xsd:int" use="required" />
      <xsd:attribute name="timestamp" type="xsd:dateTime" use="required" />
     <xsd:anyAttribute processContents="lax" />
    </xsd:complexType>
  </xsd:element>

    <xsd:complexType name="any_complex_type">
        <xsd:complexContent>
            <xsd:restriction base="xsd:anyType">
                <xsd:sequence>
                    <xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
                </xsd:sequence>
                <xsd:anyAttribute processContents="lax" />
            </xsd:restriction>
        </xsd:complexContent>
    </xsd:complexType>
</xsd:schema>';

go 

Примеры типов конструкций, которые я строю:

declare @test [xml]([chamomile].[xsc_test_stack]) = N'
     <chamomile:test_stack xmlns:chamomile="https://github.com/KELightsey/chamomile" name="[chamomile].[person_test].[get_age]" test_count="2" pass_count="2" timestamp="2018-06-24T15:50:19.3466667">
       <description>This test stack consists of tests which validate the functionality of the age calculation for a person.</description>
     </chamomile:test_stack>';
go

declare @test [xml]([chamomile].[xsc_test_stack]) = N'
     <chamomile:test_stack xmlns:chamomile="https://github.com/KELightsey/chamomile" name="[chamomile].[person_test].[get_age]" test_count="2" pass_count="2" timestamp="2018-06-24T15:50:19.3466667">
       <description>This test stack consists of tests which validate the functionality of the age calculation for a person.</description>
       <test_stack_detail>
          <any_valid_xml_goes_here />
       </test_stack_detail>
     </chamomile:test_stack>';
go

Что я пробовалis:

set @test_stack.modify(N'replace value of (//@test_count)[1] with sql:variable("@count")');

Возвращает : сообщение 9306, уровень 16, состояние 1, строка 28 XQuery [modify ()]: цель «заменить значение» не можетбыть найденным типом объединения '(атрибут (test_count, xs: int) | атрибут (test_count, xs: anySimpleType))?'.

set @test_stack.modify(N'declare namespace chamomile="https://github.com/KELightsey/chamomile"; 
    replace value of (chamomile:test_stack/@test_count)[1] with sql:variable("@count")');

Возвращает : сообщение 9306,Уровень 16, состояние 1, строка 25 XQuery [modify ()]: цель «заменить значение» не может быть найден тип объединения (атрибут (test_count, xs: int) | атрибут (test_count, xs: anySimpleType))? "Есть много, много примеров с нетипизированным XML, и несколько примеров с типизированным XML, которые все еще выдают те же исключения.

Я был бы признателен за некоторую проницательность.

Спасибо, Кэтрин

1 Ответ

0 голосов
/ 26 июня 2018

Должен признать, что я тоже не нашел прямого подхода.Кажется, это ошибка, по крайней мере, я не вижу в этом смысла.Обходной путь - это простое приведение, но оно очень близко к тому, что вы описываете в своих начальных строках:

declare @test [xml]([chamomile].[xsc_test_stack]) = 
N'<chamomile:test_stack xmlns:chamomile="https://github.com/KELightsey/chamomile" name="[chamomile].[person_test].[get_age]" test_count="2" pass_count="2" timestamp="2018-06-24T15:50:19.3466667">
       <description>This test stack consists of tests which validate the functionality of the age calculation for a person.</description>
     </chamomile:test_stack>';

DECLARE @cnt INT=99;

DECLARE @intermediate XML=CAST(@test AS XML); --magic happens here
SET @intermediate.modify('declare namespace chamomile="https://github.com/KELightsey/chamomile"; 
                          replace value of (chamomile:test_stack/@test_count)[1] with sql:variable("@cnt")');

SET @test=@intermediate; --re-assign to typed XML

SELECT @test;
...