I am just starting with xquery and currently I don’t know, why the following is not working. I’ve created two XML files, they are identically, except that one has namespaces and the other doesn’t:
<Envelope>
<Header>
<JustAValue>12345</JustAValue>
</Header>
<Body>
<someBody>
<ValueIWant>12345678910</ValueIWant>
</someBody>
</Body>
</Envelope>
<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
<env:Header xmlns:wsa='http://www.w3.org/2005/08/addressing'>
<JustAValue>12345</JustAValue>
</env:Header>
<env:Body xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd' wsu:Id='element-28-1344266615792-223644235'>
<ns1:someBody xmlns='http://someURL.com' xmlns:ns1='http://someURL.com'>
<ValueIWant>12345678910</ValueIWant>
</ns1:someBody>
</env:Body>
</env:Envelope>
Both xml files are in a xml field in the database.
Now I try to get the “ValueIWant” and I do it like this:
DECLARE @xml xml
Select @xml = completexml from MyDB.dbo.Xml where PKxml = 3 -- XML without namespaces
declare @somevalue nvarchar(max)
set @somevalue = @xml.value('(/Envelope/Body/someBody/ValueIWant/text())[1]', 'nvarchar(max)');
select @somevalue -- -> 12345678910
Select @xml = completexml from MyDB.dbo.Xml where PKxml = 2 -- XML with namespaces
set @somevalue = @xml.value('
declare namespace env="http://schemas.xmlsoap.org/soap/envelope/";
declare namespace ns1="http://someURL.com";
(/env:Envelope/env:Body/ns1:someBody/ValueIWant/text())[1]', 'nvarchar(max)');
select @somevalue -- -> NULL
What am I doing wrong here?
I’ve played around a bit with the XML:
<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
<env:Header xmlns:wsa='http://www.w3.org/2005/08/addressing'>
<JustAValue>12345</JustAValue>
</env:Header>
<env:Body xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd' wsu:Id='element-28-1344266615792-223644235'>
<ns1:someBody xmlns='http://someURL.com' xmlns:ns1='http://someURL.com'>
<ValueIWant>12345678910</ValueIWant>
</ns1:someBody>
<BodyValue>BodyValue</BodyValue>
<env:BodyValue>BodyValue</env:BodyValue>
</env:Body>
<env:TestValue1>TestValue</env:TestValue1>
<TestValue2>TestValue2</TestValue2>
</env:Envelope>
I can get all the values: BodyValue, TestValue1 and TestValue2. No problem at all, but as soon as I want to change into the ns1 namespace and get ValueIWant, it just returns NULL.
The ValueIWant element tag name is in the default namespace (http://someURL.com), because this namespace is bound to the empty prefix by its parent element:
However in the query there seems to be no default namespace, so that the name test ValueIWant does not match the ValueIWant tag.
Since it is the same URL that is bound to the ns1 prefix, perhaps prefixing ValueIWant with ns1 in your XPath expression would solve the problem?
Alternatively, you could add a
in your query. But using the ns1 prefix should normally work as well, because when comparing names (“QNames”), only the namespace and the local name matter, the prefix is irrelevant.