I have a column that contains the following xml:
<obj xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:vim25" versionId="5.1" xsi:type="ArrayOfKeyAnyValue">
<KeyAnyValue xsi:type="KeyAnyValue">
<key>1</key>
<value xsi:type="xsd:string">naa.6019cbc1a09e175d370df5320b00803a</value>
</KeyAnyValue>
<KeyAnyValue xsi:type="KeyAnyValue">
<key>2</key>
<value xsi:type="xsd:string">6215</value>
</KeyAnyValue>
<KeyAnyValue xsi:type="KeyAnyValue">
<key>3</key>
<value xsi:type="xsd:string">1291898</value>
</KeyAnyValue>
</obj>
I wish to return each of the key values as a separate column. I have tried:
SELECT [table].[column1]
,CONVERT(xml, [table].[column1]).value('(/obj/KeyAnyValue[1]/value)[1]', 'nvarchar(max)') As KeyValue
from [table]
This just returns NULL. Have I got the XML path right?
Sure something simple I am doing wrong and much appreciate any help.
Thanks
Your XPath expression has to say what namespace it's working with:
declare #data xml = '<obj xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:vim25" versionId="5.1"
xsi:type="ArrayOfKeyAnyValue">
<KeyAnyValue xsi:type="KeyAnyValue">
<key>1</key>
<value xsi:type="xsd:string">naa.6019cbc1a09e175d370df5320b00803a</value>
</KeyAnyValue>
<KeyAnyValue xsi:type="KeyAnyValue">
<key>2</key>
<value xsi:type="xsd:string">6215</value>
</KeyAnyValue>
<KeyAnyValue xsi:type="KeyAnyValue">
<key>3</key>
<value xsi:type="xsd:string">1291898</value>
</KeyAnyValue>
</obj>'
select #data.value('declare namespace a="urn:vim25";
(/a:obj/a:KeyAnyValue[1]/a:value)[1]', 'nvarchar(max)')
Produces:
naa.6019cbc1a09e175d370df5320b00803a
Related
I have an SQL query which returns two columns with data like this:.
State Name
------- ---------
Online Terminal1
Offline Terminal2
Online Terminal3
Online Terminal4
Now I want to create an XML file with a SQL query runs. XML file structure must be like this:
<?xml version="1.0" encoding="utf-8" ?>
<Terminallist name="xml data">
<Value id="0">
<Terminal>Terminal1</Terminal>
<State>Online</State>
</Value>
<Value id="1">
<Terminal>Terminal2</Terminal>
<State>Offline</State>
</Value>
<Value id="2">
<Terminal>Terminal3</Terminal>
<State>Online</State>
</Value>
<Value id="3">
<Terminal>Terminal4</Terminal>
<State>Online</State>
</Value>
</Terminallist>
I want to save XML file to a directory like this c:/file.xml.
Answer:-
Table name: temptable
Data in table :
Query :-
SELECT XMLElement("Terminallist ", XMLAttributes('xml data' AS "name"),XMLAgg(XMLElement("value ", XMLAttributes(rownum AS "id"),XMLForest(Terminal,state))))
FROM temptable ;
output :-
<Terminallist name = "xml data">
<value id = "1">
<TERMINAL>Terminal2</TERMINAL>
<STATE>Offline</STATE>
</value>
<value id = "2">
<TERMINAL>Terminal3</TERMINAL>
<STATE>Online</STATE>
</value>
<value id = "3">
<TERMINAL>Terminal4</TERMINAL>
<STATE>Online</STATE>
</value>
</Terminallist>
Thanks
Narendar
This solution uses a WITH clause to generate the ID as you want, starting from 0. Using the analytic row_number() function provides a guaranteed sort order in the result set.
NB: XMLRoot() is deprecated as part of the XML/SQL standard but generates the version header you asked for. Find out more.
with cte as (
select row_number() over (order by name) - 1 as id
, name
, state
from terminals
)
SELECT xmlroot (
XMLElement(
"Terminallist",
XMLAttributes( 'xml data' as "name"),
XMLAgg(XMLElement("Value",
XMLAttributes(cte.id as "id"),
XMLElement("Terminal",cte.name),
XMLElement("State",cte.state)
)
)
)
, version '1.0' )
FROM cte
order by cte.id
/
Here is the output:
<?xml version="1.0"?>
<Terminallist name="xml data">
<Value id="0">
<Terminal>Terminal1</Terminal>
<State>Online</State>
</Value>
<Value id="1">
<Terminal>Terminal2</Terminal>
<State>Offline</State>
</Value>
<Value id="2">
<Terminal>Terminal3</Terminal>
<State>Online</State>
</Value>
<Value id="3">
<Terminal>Terminal4</Terminal>
<State>Online</State>
</Value>
</Terminallist>
As for writing the output to a file, that depends on how you want to call the SQL. Use SPOOL if you're running it from SQL*Plus and want to save it to a local file. If running from PL/SQL you'll need to use UTL_FILE and write to a directory on the database server.
Using the Oracle XE database as source data I'm able to export the employees table as XML as follows...
SELECT SYS_XMLAGG(
SYS_XMLGEN(
XMLFOREST(employee_id, first_name, last_name, email, phone, hire_date, manager_id, job_title)
)
) FROM employees;
The XML will look like...
<?xml version="1.0"?>
<ROWSET>
<ROW>
<EMPLOYEE_ID>107</EMPLOYEE_ID>
<FIRST_NAME>Summer</FIRST_NAME>
<LAST_NAME>Payne</LAST_NAME>
<EMAIL>summer.payne#example.com</EMAIL>
<PHONE>515.123.8181</PHONE>
<HIRE_DATE>2016-06-07</HIRE_DATE>
<MANAGER_ID>106</MANAGER_ID>
<JOB_TITLE>Public Accountant</JOB_TITLE>
</ROW>
<ROW>
<EMPLOYEE_ID>...
The CSV list of column names for XMLForest can be obtained thus...
SELECT LISTAGG(column_name, ',') FROM user_tab_columns WHERE table_name = 'EMPLOYEES';
Luck.
I need to parser a SOAP xml in SQL Server and convert it to table
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<ExecCommandResponse xmlns="http://tempuri.org/">
<ExecCommandResult>
<Result xmlns="">
<row>
<LOT>VERL5B3002PL</LOT>
<ID>115</ID>
<WH>710</WH>
<STPL>12</STPL>
</row>
<row>
<LOT>VERL68804EVN</LOT>
<ID>3716</ID>
<WH>771</WH>
<STPL>6</STPL>
</row>
</Result>
</ExecCommandResult>
</ExecCommandResponse>
</soap:Body>
</soap:Envelope>
I need to parser a SOAP xml in sql server and convert it to table
LOT | ID | WH | STPL
VERL68804EVN | 3716 | 771 | 6
Use the up-to-date functions to query XML.
Your XML is not very clean looking on the namespaces. There are two default namespaces, one of them empty... Therefore I would avoid (mask) them entirely.
DECLARE #xml XML=
'<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<ExecCommandResponse xmlns="http://tempuri.org/">
<ExecCommandResult>
<Result xmlns="">
<row>
<LOT>VERL5B3002PL</LOT>
<ID>115</ID>
<WH>710</WH>
<STPL>12</STPL>
</row>
<row>
<LOT>VERL68804EVN</LOT>
<ID>3716</ID>
<WH>771</WH>
<STPL>6</STPL>
</row>
</Result>
</ExecCommandResult>
</ExecCommandResponse>
</soap:Body>
</soap:Envelope>';
SELECT r.value('LOT[1]','varchar(max)') AS LOT
,r.value('ID[1]','int') AS ID
,r.value('WH[1]','int') AS WH
,r.value('STPL[1]','int') AS STPL
FROM #xml.nodes('/*:Envelope/*:Body/*:ExecCommandResponse/*:ExecCommandResult/*:Result/*:row') AS A(r)
--or even simpler (would even work without the *:):
SELECT r.value('LOT[1]','varchar(max)') AS LOT
,r.value('ID[1]','int') AS ID
,r.value('WH[1]','int') AS WH
,r.value('STPL[1]','int') AS STPL
FROM #xml.nodes('//*:row') AS A(r)
In general I'd say: Be as specific as possible, therefore rather suggest the first...
Try Below. See if it works.
declare #xmldata xml = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<ExecCommandResponse>
<ExecCommandResult>
<Result xmlns="">
<row>
<LOT>VERL5B3002PL</LOT>
<ID>115</ID>
<WH>710</WH>
<STPL>12</STPL>
</row>
<row>
<LOT>VERL68804EVN</LOT>
<ID>3716</ID>
<WH>771</WH>
<STPL>6</STPL>
</row>
</Result>
</ExecCommandResult>
</ExecCommandResponse>
</soap:Body>
</soap:Envelope>'
declare #readdoc as INT
EXEC sp_xml_preparedocument #readdoc OUTPUT, #xmldata , '<root xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />'
select LOT,ID,WH,STPL
from OPENXML(#readdoc,'soap:Envelope/soap:Body/ExecCommandResponse/ExecCommandResult/Result/row')
with
(
LOT [varchar](50) 'LOT',
ID [varchar](50) 'ID',
WH [varchar](50) 'WH',
STPL [varchar](50) 'STPL'
)
EXEC sp_xml_removedocument #readdoc
GO
Below is the output.
I have table DOCUMENTS with:
DOCUMENTS
____________________
DOCUMENTID int
USERID int
CONTENT text
I have following XML stored in TEXT column with name CONTENT in a SQL Server database
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<IDMSDocument>
<DocumentContent>
<Attribute Name="Number" GUID="{FFFFFFFF-0000-0000-0000-000000000001}">
<IDMSType>3060</IDMSType>
<Value Type="Integer">
<Value>122</Value>
</Value>
</Attribute>
<Attribute Name="Date" GUID="{FFFFFFFF-0000-0000-0000-000000000002}">
<IDMSType>3061</IDMSType>
<Value Type="DateTime">
<Date>10-09-2014</Date>
</Value>
</Attribute>
<Attribute Name="Публикуване" GUID="{CA646F55-5229-4FC5-AA27-494B25023F4E}">
<IDMSType>3062</IDMSType>
<Value Type="String">
<Value>Да</Value>
</Value>
</Attribute>
<Attribute Name="Дата" GUID="{AC0465B0-4FB4-49E2-B4FA-70901068FD9B}">
<IDMSType>3063</IDMSType>
<Value Type="DateTime">
<Date>01-10-2014</Date>
</Value>
</Attribute>
<Attribute Name="Предмет на поръчка" GUID="{04A4EC72-6F33-461F-98DD-D8D271997788}">
<IDMSType>3065</IDMSType>
<Value Type="String">
<Value>Избор на консултанти</Value>
</Value>
</Attribute>
</DocumentContent>
</IDMSDocument>
I find a way how to query dingle XML attribute in a single row from table, with heavy conversion :
DECLARE #strContent NVARCHAR(MAX);
DECLARE #xmlContent XML;
SET #strContent = (select content from DOCUMENTS where DocumentID=24);
SET #xmlContent = CAST(REPLACE(CAST(#strContent AS NVARCHAR(MAX)),'utf-8','utf-16') AS XML)
SELECT #xmlContent.query('/IDMSDocument/DocumentContent/Attribute[5]/Value/Value')
where #xmlContent.value('(/IDMSDocument/DocumentContent/Attribute[5]/Value/Value)[1]', 'nvarchar(max)') like '%search%'
I need to make query like "select all rows in table that in fifth attribute in XML have value 'search' "
For me the general problem is that column type is not XML, but I have text column with stored xml inside. when I try cast, query, value directly server return that I can use it Only with XML column.
I would be very grateful if someone suggest how to do this!
Thanks!
Kamen
SQL Server doesn't allow inline XML conversion to have functions applied, i.e.: no CAST(...).query(), use a CTE to handle the conversion:
;WITH cte AS (
SELECT DocumentID, UserID, CAST(Content AS XML) AS XMLContent
FROM Documents
)
SELECT XMLContent.query('/IDMSDocument/DocumentContent/Attribute[5]/Value/Value')
FROM cte
WHERE XMLContent.value('(/IDMSDocument/DocumentContent/Attribute[5]/Value/Value)[1]', 'nvarchar(max)') like '%search%'
One thing though: I saw Unicode (Russian?) characters in the Content column. It may be better to use utf-16 in your XML and ntext for column type.
text and ntext are also on the way out. If this is new code, use nvarchar(max)
I'm trying to extract a given set of values from an xmlfield blob data type.
The Xml structure looks like
<?xml version="1.0" encoding="UTF-8"?>
<ItemParameters type="**XYZ" version="000000000">
<Attribute name="Item ID" elementaryType="Numeric">
<Value value="12"></Value>
</Attribute>
<Attribute name="A" elementaryType="B">
<Value value="50"></Value>
</Attribute>
</ItemParameters>
<Scales>
</Scales>
where I'd like to check if attribute name = A and elementryType = B and extract the value beneeth in this case 50.
I tried doing like
select xmltype (dynamic_data).EXTRACT ('//ItemParameters/Attribute/Value()').getVal ()
Which is not working
I have an XML type column in SQL server:
<LogMessage xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="LogMessageBusinessServiceRequest">
<Application>Services.Business.myapp</Application>
<Time>2013-05-30T15:01:38.932Z</Time>
<Level>Info</Level>
<Message>MultiQuery Biz Request</Message>
<MachineName>Machine1</MachineName>
<ThreadId>16084</ThreadId>
<Callsite>BLAH</Callsite>
<CreatedBy>Machine1\svc_biz_myapp</CreatedBy>
<Context>
<myappExtraInfo xmlns="http://services.somedomain.com/myapp/logging/extraInfo" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<CallType>MultiProcessQuery</CallType>
<RequestId>r163505508498822282742</RequestId>
<FirmId>160</FirmId>
<PMFirmId>203</PMFirmId>
<SubscriptionId>0</SubscriptionId>
<Token />
<LastClientSvcTimeMs>0</LastClientSvcTimeMs>
<ResultCode>0</ResultCode>
<ResultCodeDescription>OK</ResultCodeDescription>
<ElapsedTimeTotalMs>110</ElapsedTimeTotalMs>
<ElapsedTimeMtMs>110</ElapsedTimeMtMs>
<ElapsedTimeDacMs>109</ElapsedTimeDacMs>
<ElapsedTimePMSSMs>-1</ElapsedTimePMSSMs>
</myappExtraInfo>
</Context>
I want to get the FirmID from there. But I am not able with the following section of my select statement:
select
[Body].value('(/LogMessage/Context/myappExtraInfo/FirmId)[1]', 'varchar(max)') FirmID
What am I doing wrong?
Thanks for your time.
Shiyam
Try this - you need to respect the XML namespace that's defined on your <myappExtraInfo> node (and thus applies to all subnodes, too):
DECLARE #Test TABLE (ID INT NOT NULL, XmlContent XML)
INSERT INTO #Test VALUES(1,
'<LogMessage xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="LogMessageBusinessServiceRequest">
<Application>Services.Business.myapp</Application>
<Time>2013-05-30T15:01:38.932Z</Time>
<Level>Info</Level>
<Message>MultiQuery Biz Request</Message>
<MachineName>Machine1</MachineName>
<ThreadId>16084</ThreadId>
<Callsite>BLAH</Callsite>
<CreatedBy>Machine1\svc_biz_myapp</CreatedBy>
<Context>
<myappExtraInfo xmlns="http://services.somedomain.com/myapp/logging/extraInfo" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<CallType>MultiProcessQuery</CallType>
<RequestId>r163505508498822282742</RequestId>
<FirmId>160</FirmId>
<PMFirmId>203</PMFirmId>
<SubscriptionId>0</SubscriptionId>
<Token />
<LastClientSvcTimeMs>0</LastClientSvcTimeMs>
<ResultCode>0</ResultCode>
<ResultCodeDescription>OK</ResultCodeDescription>
<ElapsedTimeTotalMs>110</ElapsedTimeTotalMs>
<ElapsedTimeMtMs>110</ElapsedTimeMtMs>
<ElapsedTimeDacMs>109</ElapsedTimeDacMs>
<ElapsedTimePMSSMs>-1</ElapsedTimePMSSMs>
</myappExtraInfo>
</Context>
</LogMessage>')
;WITH XMLNAMESPACES('http://services.somedomain.com/myapp/logging/extraInfo' AS ns)
SELECT
XmlContent.value('(/LogMessage/Context/ns:myappExtraInfo/ns:FirmId)[1]', 'int')
FROM #Test
WHERE ID = 1
This returns the value 160 to me.