Ошибка XQuery при чтении атрибута из родительского узла с * typed * XML (значение () требует одиночного) - PullRequest
1 голос
/ 27 марта 2019

У меня есть простой XML:

DECLARE @x1 xml = '<r>
    <o a="1">
        <o a="2">
        </o>
    </o>
</r>';

И выберите следующее:

SELECT r.o.value('(../@a)[1]','varchar(20)') FROM @x1.nodes('/r//o') r(o);

Все хорошо:

NULL
1

Когда я использую типизированный XML:

CREATE XML SCHEMA COLLECTION [dbo].test AS '
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="r">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:restriction base="xsd:anyType">
                    <xsd:sequence>
                        <xsd:element name="o" type="o" minOccurs="0" maxOccurs="unbounded" />
                    </xsd:sequence>
                </xsd:restriction>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>
    <xsd:complexType name="o">
        <xsd:complexContent>
            <xsd:restriction base="xsd:anyType">
                <xsd:sequence>
                    <xsd:element name="o" type="o" minOccurs="0" maxOccurs="unbounded" />
                </xsd:sequence>
                <xsd:attribute name="a" type="xsd:string" />
            </xsd:restriction>
        </xsd:complexContent>
    </xsd:complexType>
</xsd:schema>'
GO

DECLARE @x2 xml(dbo.test) = '<r>
    <o a="1">
        <o a="2">
        </o>
    </o>
</r>';

SELECT r.o.value('(../@a)[1]','varchar(20)') FROM @x2.nodes('/r//o') r(o);

Я получил ошибку:

XQuery [value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'

Почему нетипизированный XML работает, а типизированный XML - нет?

1 Ответ

0 голосов
/ 27 марта 2019

Похоже, вы хорошо понимаете, что это не обычная проблема убеждения синтаксического анализатора в том, что в value() передается только одна вещь. Эта проблема характерна для типизированного XML , как вы заметили.

С помощью Google я нашел этот древний пост с многообещающим текстом

rt является частью модели данных XQuery 1.0 / XPath 2.0.

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

В нем говорится о SQL Books Online и документе о наилучшей практике XML для SQL Server 2005, который, как мне кажется, является этой книгой . Я не искал более актуальную ссылку. Но используя то, что я нашел там, я смог решить вашу проблему: Простая замена

SELECT r.o.value('(../@a)[1]','varchar(20)') FROM @x2.nodes('/r//o') r(o);

с

SELECT r.o.value('fn:string(../@a)[1]','varchar(20)') FROM @x2.nodes('/r//o') r(o);

По сути, value() не нравится, когда ему присваиваются значения typeed-xml-type, но нужны строки. Итак, мы даем ему строку.

...