I have an XML column in a large table that looks like this, in TSQL how would i count the number of times an attribute (LCPID) occurs?
Thanks,
The code:
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<PingAutoRequest xmlns="http://Reply.LeadMarketPlace.Services.Ping.ServiceContracts/2007/10/ServiceContracts">
<AutomotiveLead>
<LCPId>766</LCPId>
<Zipcode>33544</Zipcode>
<Make>Ford</Make>
<Model>Escape</Model>
<LeadType>New</LeadType>
<Year>2013</Year>
<Trim>FWD S</Trim>
<ExteriorColor />
<InteriorColor />
<Transmission />
<TradeIn>false</TradeIn>
<LastFourPhoneDigits />
<LastName />
</AutomotiveLead>
</PingAutoRequest>
</soap:Body>
</soap:Envelope>
OK, as your XML doesn't contain any attributes (apart from the namespaces) I'm going to assume you mean you want to count the number of <LCPId> elements. If so, then you could do that like this...
;WITH XMLNAMESPACES ('http://Reply.LeadMarketPlace.Services.Ping.ServiceContracts/2007/10/ServiceContracts' as ns)
SELECT XmlColumn.value('(count(//ns:LCPId))','int')
FROM YourTableName
Note, we need to handle the XML namespace using the WITH statement, the semi-colon is not a mistake. Then we count the number of elements with an XPath expression count(//ns:LCPId).
You can see it in action at SQL Fiddle here.
Related
We have an in-house piece of software that works with loosely-defined XML files. I'm trying to extract the child nodes from this step in T-SQL. I'm able to extract the parent node, but I keep getting <eof> syntax errors whenever I query the children.
The XML file looks roughly like this:
<?xml version="1.0"?>
<root>
<steps>
<step>
<steptypeX attribute="somevalue">
<child1>Value</child1>
<child2>Value</child2>
</steptypeX>
</step>
</steps>
</root>
I'm using the following T-SQL:
select
doc.col.query('/child*') --If I use '.' or '*' here I can get the children as XML, but I want the values contained within the nodes on separate rows
from #xmldoc.nodes('/root/steps/step/steptypeX') doc(col)
where doc.col.value('#attribute', 'nvarchar(max)') = 'somevalue'
The error message I'm getting is not clear:
XQuery [query()]: Syntax error near '<eof>'
As far as I can tell, the nodes do exist and I haven't left any XQuery instructions with trailing slashes. I can't really tell what I'm doing wrong here.
If I understand your intention correctly you can use child::*:
DECLARE #xmldoc XML =
N'<?xml version="1.0"?>
<root>
<steps>
<step>
<steptypeX attribute="somevalue">
<child1>Value</child1>
<child2>Value</child2>
</steptypeX>
</step>
</steps>
</root>';
SELECT
doc.col.value('text()[1]', 'nvarchar(max)')
FROM #xmldoc.nodes('/root/steps/step/steptypeX/child::*') doc(col)
WHERE doc.col.value('../#attribute', 'nvarchar(max)') = 'somevalue';
LiveDemo
I have the following xquery piece, I'm trying to test outside of my t-sql script:
DECLARE #x XML
SELECT #x = N'<?xml version="1.0" encoding="utf-16"?>
<Root xmlns="http://www.w3.org">
<Header>
<Record>
<A99>
<A99_01_0>
<A99_01>TEST</A99_01>
<A99_02>TEST</A99_02>
<A99_03>TEST</A99_03>
</A99_01_0>
</A99>
</Record>
</Header>
</Root>
';
select #x.exist('//Header/Record/A99/A99_01_0/A99_01')
I simply want to check if there is a value between the A99_01 tags, which there is. But according to my exist(), my output keeps coming back as 0, indicating that it doesn't exist.
Is there something I'm missing? I've double checked to make sure my syntax for the exist() is correct. Any help would be greatly appreciated!
Yes - you're missing the XML namespace defined in your XML document!
SELECT #x = N'<?xml version="1.0" encoding="utf-16"?>
<Root xmlns="http://www.w3.org">
*************************
You need to change your SELECT to:
WITH XMLNAMESPACES(DEFAULT 'http://www.w3.org')
SELECT
#x.exist('//Header/Record/A99/A99_01_0/A99_01')
I need to get some information from XML in SQL Server 2008, but I cannot even get basic attribute from it. All samples that I tried failed. Table name is Item, xml column name is Data.
Simplified xml looks like this:
<AnchoredXml xmlns="urn:schema:Microsoft.Rtc.Management.ScopeFramework.2008" SchemaWriteVersion="2">
<Key ScopeClass="Global">
<SchemaId Namespace="urn:schema:Microsoft.Rtc.Management.Deploy.Topology.2008" ElementName="Topology" />
<AuthorityId Class="Host" InstanceId="00000000-0000-0000-0000-000000000000" />
</Key>
<Dictionary Count="1">
<Item>
<Key />
<Value Signature="a3502dd0-8c16-4023-9eea-30ea1c7a3a2b">
<Topology xmlns="urn:schema:Microsoft.Rtc.Management.Deploy.Topology.2008">
<Services>
<Service RoleVersion="1" ServiceVersion="6" Type="Microsoft.Rtc.Management.Deploy.Internal.ServiceRoles.FileStoreService">
<ServiceId SiteId="1" RoleName="FileStore" Instance="1" />
<DependsOn />
<InstalledOn>
<ClusterId SiteId="1" Number="1" />
</InstalledOn>
<Ports xmlns="urn:schema:Microsoft.Rtc.Management.Deploy.ServiceRoles.2008" />
<FileStoreService xmlns="urn:schema:Microsoft.Rtc.Management.Deploy.ServiceRoles.2008" ShareName="lyncShare" />
</Service>
</Services>
</Topology>
</Value>
</Item>
</Dictionary>
</AnchoredXml>
I need to read information in AnchoredXml/Key/SchemaId/#NameSpace to select the right xml (there are more rows). Sample xml above is the right one. And after that I need to find the right service with
Type="Microsoft.Rtc.Management.Deploy.Internal.ServiceRoles.FileStoreService"
where is FileStoreService/#ShareName that I need.
I've tried to print the Namespace attributte for the start, but no sample code is working.
A few tries:
SELECT c.p.value('(#Namespace)[1]', 'varchar(50)') as 'Nmspace'
FROM Item
CROSS APPLY Data.nodes('/AnchoredXml/Key/SchemaId') c(p)
returns empty result set
SELECT Data.value('(/AnchoredXml/Key/SchemaId/#Namespace)[1]', 'varchar(50)')
FROM Item
returns NULL for all rows
SELECT
It.Data.exist('/AnchoredXml/Key/SchemaId[#Namespace="Microsoft.Rtc.Management.Deploy.Topology.2008"]')
FROM [xds].[dbo].[Item] AS It
returns 0's for all rows also without quotes ("")
A working sample code to get at least attribute test would be maybe sufficient and I would figure out the rest.
Could you please help me find errors in my queries or maybe identify some other problem?
Thanks
You're ignoring all the XML namespaces in your XML document! You need to pay attention to those and respect them!
There are XML namespaces on:
the root node <AnchoredXml>
(XML namespace: urn:schema:Microsoft.Rtc.Management.ScopeFramework.2008)
the subnode <Topology>
(XML ns: urn:schema:Microsoft.Rtc.Management.Deploy.Topology.2008)
the subnode <FileStoreService>
(XML ns: urn:schema:Microsoft.Rtc.Management.Deploy.ServiceRoles.2008)
Try this:
-- respect the XML namespaces!!
;WITH XMLNAMESPACES(DEFAULT 'urn:schema:Microsoft.Rtc.Management.ScopeFramework.2008',
'urn:schema:Microsoft.Rtc.Management.Deploy.Topology.2008' AS t,
'urn:schema:Microsoft.Rtc.Management.Deploy.ServiceRoles.2008' AS fss)
SELECT
ShareName = Data.value('(/AnchoredXml/Dictionary/Item/Value/t:Topology/t:Services/t:Service/fss:FileStoreService/#ShareName)[1]', 'varchar(50)')
FROM
dbo.Item
In my case, this returns:
ShareName
-----------
lyncShare
I have a column in table with datatype XML.
mycolumn has following value
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www
.w3.org/2001/XMLSchema"
xmlns:ns1="http://http://localhost/test/">
<SOAP-ENV:Body>
<ns1:IDResults>
<NCNL>
<Value>123</Value>
</NCNL>
</ns1:IDResults>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
select mycolumn.query('./Envelope/Body')
My above select statement does not return anything.
Do I need to specify SOAP-ENV: prefix, if yes than how do I specify it?
Thanks in advance.
The actual query depends on what you want to get, but basically you have to specify namespace in your query, like this:
;with xmlnamespaces ('http://schemas.xmlsoap.org/soap/envelope/' as [SOAP-ENV])
select #data.query('SOAP-ENV:Envelope/SOAP-ENV:Body/*')
I'm trying to get some values out of an Xml Datatype. The data looks like:
<Individual xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<FirstName xmlns="http://nswcc.org.au/BusinessEntities.Crm">Lirria</FirstName>
<LastName xmlns="http://nswcc.org.au/BusinessEntities.Crm">Latimore</LastName>
</Indvidual>
Note the presence of the xmlns in the elements FirstName and LastName - this is added when we create the xml by serializing a c# business object. Anyway it seems that the presence of this namespace in the elements is causing XQuery expressions to fail, such as:
SELECT MyTable.value('(//Individual/LastName)[1]','nvarchar(100)') AS FirstName
This returns null. But when I strip out the namespace from the elements in the xml (e.g. using a Replace T-SQL statement), the above returns a value. However there must be a better way - is there a way of making this query work i.e. without updating the xml first?
Thanks
John Davies
You need to properly name the element you want to select. See Adding Namespaces Using WITH XMLNAMESPACES. Here is an example using your XML:
declare #x xml;
set #x = N'<Individual
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<FirstName xmlns="http://nswcc.org.au/BusinessEntities.Crm">Lirria</FirstName>
<LastName xmlns="http://nswcc.org.au/BusinessEntities.Crm">Latimore</LastName>
</Individual>';
with xmlnamespaces (N'http://nswcc.org.au/BusinessEntities.Crm' as crm)
select #x.value(N'(//Individual/crm:LastName)[1]',N'nvarchar(100)') AS FirstName
The * wildcard will also allow you to select the element without enforcing the explicit namespace. Remus' answer is the way to go, but this may assist others having namespace issues:
select #x.value(N'(//Individual/*:LastName)[1]',N'nvarchar(100)')