2

I have a table named Audit.Event which captures user events, one of the columns within that table stores the data as xml, which is structured as such

XML Data

<OrganisationSearchEvent xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Options>
    <IsAgency>false</IsAgency>
    <IsCharity>false</IsCharity>
    <IsCompany>false</IsCompany>
    <IsEducationalEstablishment>false</IsEducationalEstablishment>
    <IsProgrammeProvider>false</IsProgrammeProvider>
    <Name i:nil="true" />
    <OrganisationIDs xmlns:d3p1="http://schemas.datacontract.org/2004/07/System" i:nil="true" />
    <ProfessionalBodies xmlns:d3p1="http://schemas.datacontract.org/2004/07/System" i:nil="true" />
    <Sectors xmlns:d3p1="http://schemas.datacontract.org/2004/07/System">
      <d3p1:int>21</d3p1:int>
      <d3p1:int>82</d3p1:int>
    </Sectors>
    <SubSector xmlns:d3p1="http://schemas.datacontract.org/2004/07/System" i:nil="true" />
  </Options>
  <Paging>
    <EndRecord i:nil="true" />
    <PageNumber>1</PageNumber>
    <PagingMode>Paged</PagingMode>
    <RecordsPerPage>20</RecordsPerPage>
    <StartRecord i:nil="true" />
    <TotalPages>1</TotalPages>
  </Paging>
</OrganisationSearchEvent>

I need to shred the xml and capture the data in the elements named d3p1:int. So far I have wrote the following query:

Query

SELECT 
Data.value('(//d3p1:int)[1]', 'int') AS [SectorID],
FROM [Audit].[EventData]
Cross Apply Data.nodes('//OrganisationSearchEvent/Options/Sectors') as Test(X)
Where EventTypeID = 7 
Order By CapturedDateTime Desc

All I would expect to see is

+----------+
| SectorID |
+----------+
|       10 |
|       45 |
|       50 |
|       22 |
|        6 |
+----------+

But instead I get the following error

The name "d3p1" does not denote a namespace.

If I replace "d3p1:int" with just "d3p1", nulls are returned

If I use the following line in the select clause as a test, the correct data for that element is returned.

Data.value('(//Name)[1]','nvarchar(100)') AS [Name]

Could anyone point me in the right direction, am unsure what the actual cause of this is

Thanks

--Edit--

Following Shnugo's suggestion I have tried the following with no luck, I must be missing something!

I am unable to point to the actual XMLdata as shown as this is being stored via the application into a column in the "Autit.EventData" table, what I tried to do is this.

Attempt 1

Declare @xml XML=[Audit].[EventData].[Data]

;WITH XMLNAMESPACES ('http://www.w3.org/2001/XMLSchema-instance' AS d3p1)
SELECT i.value('.','int') AS [SectorID]
FROM @xml.nodes('/OrganisationSearchEvent/Options/Sectors/d3p1:int') as A(i)

But I get the error

The multi-part identifier "Audit.EventData.Data" could not be bound.

I assume I still need to use the table so I tried this next

Attempt 2

;WITH XMLNAMESPACES ('http://www.w3.org/2001/XMLSchema-instance' AS d3p1)
SELECT i.value('.','int') AS [SectorID]
FROM [Audit].[EventData]

Cross Apply Data.nodes('/OrganisationSearchEvent/Options/Sectors/d3p1:int') as A(i)

but this returns nothing

Final Solution

Here is the final query I used to return the correct data

 SELECT 
T.C.value('.', 'int') as [SelectedID's] 
from Audit.[EventData] 
cross apply Data.nodes('/OrganisationSearchEvent/Options/Sectors/*') as T(C) 
where EventTypeID = 7 
order by CapturedDateTime desc 

1 Answer 1

3

Try it like this:

DECLARE @xml XML=
'<OrganisationSearchEvent xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Options>
    <IsAgency>false</IsAgency>
    <IsCharity>false</IsCharity>
    <IsCompany>false</IsCompany>
    <IsEducationalEstablishment>false</IsEducationalEstablishment>
    <IsProgrammeProvider>false</IsProgrammeProvider>
    <Name i:nil="true" />
    <OrganisationIDs xmlns:d3p1="http://schemas.datacontract.org/2004/07/System" i:nil="true" />
    <ProfessionalBodies xmlns:d3p1="http://schemas.datacontract.org/2004/07/System" i:nil="true" />
    <Sectors xmlns:d3p1="http://schemas.datacontract.org/2004/07/System">
      <d3p1:int>21</d3p1:int>
      <d3p1:int>82</d3p1:int>
    </Sectors>
    <SubSector xmlns:d3p1="http://schemas.datacontract.org/2004/07/System" i:nil="true" />
  </Options>
  <Paging>
    <EndRecord i:nil="true" />
    <PageNumber>1</PageNumber>
    <PagingMode>Paged</PagingMode>
    <RecordsPerPage>20</RecordsPerPage>
    <StartRecord i:nil="true" />
    <TotalPages>1</TotalPages>
  </Paging>
</OrganisationSearchEvent>';

WITH XMLNAMESPACES('http://schemas.datacontract.org/2004/07/System' AS d3p1)
SELECT i.value('.','int')
FROM @xml.nodes('//d3p1:int') AS A(i);

Without namespaces you might use wildcards like here

SELECT i.value('.','int')
FROM @xml.nodes('//*:int') AS A(i);

Or even the full path

WITH XMLNAMESPACES('http://schemas.datacontract.org/2004/07/System' AS d3p1)
SELECT i.value('.','int')
FROM @xml.nodes('/OrganisationSearchEvent/Options/Sectors/d3p1:int') AS A(i);

This depends on your demands. The general advise is: Be as specific as possible.

About your code: As you want to read all int-elements, you need the .nodes() to return your <d3p1:int>-elements. Your query stops one level to high. And secondly, if you have to deal with namespaces, you have either to use them explicitly or use a wildcard.

UPDATE

Without knowing your actual database it is hard to point you out...

From your question I take, that this:

SELECT 
Data.value('(//d3p1:int)[1]', 'int') AS [SectorID],
FROM [Audit].[EventData]
Cross Apply Data.nodes('//OrganisationSearchEvent/Options/Sectors') as Test(X)
Where EventTypeID = 7 
Order By CapturedDateTime Desc

together with this

Data.value('(//Name)[1]','nvarchar(100)') AS [Name]

returns the correct data?

If so, the least specific approach might be this:

SELECT 
Data.value('.','int') AS SectorID
FROM [Audit].[EventData]
Cross Apply Data.nodes('//*:int') as Test(X)
Where EventTypeID = 7 
Order By CapturedDateTime Desc

This should pick any element called int (not the datatype, the element's name!) and list this row-wise...

If you get this to work, you might try to find a more specific XPath, but this should - at least - return the correct values...

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the suggestions, I will try these out
thanks for your help this helped me get to the answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.