Convert to XML having special character name in SQL server - sql

There is a XML in the below format present in a column of datatype VARCHAR(MAX) in sql table
<?xml version="1.0" encoding="UTF-8"?>
<APIDATA xmlns="mynamespace">
<TRADE Action="Insert" CompanyID="33" Trader="Aleš Holubec"
</TRADE>
</APIDATA>
I need to fetch attribute values of Action and CompanyID . i.e, Insert and 33
In SQL, i used the below query
;WITH XMLNAMESPACES(DEFAULT 'mynamespace')
SELECT CONVERT(XML,column_name).value ('(APIDATA/TRADE/#Action)[1]', 'varchar(100)')
But i get the below error
XML parsing: line 1, character 537, illegal xml character
The reason is Aleš Holubec is the name of the trader in the XML which we cannot change.
Please help how to resolve this

You can fix this by converting your string to nvarchar(max) and then replace the encoding to UTF-16.
;WITH XMLNAMESPACES(DEFAULT 'mynamespace')
SELECT CONVERT(XML, replace(cast(column_name as nvarchar(max)), '<?xml version="1.0" encoding="UTF-8"?>', '<?xml version="1.0" encoding="UTF-16"?>')).value ('(APIDATA/TRADE/#Action)[1]', 'varchar(100)')
Or you can just remove the XML declaration.
;WITH XMLNAMESPACES(DEFAULT 'mynamespace')
SELECT CONVERT(XML, replace(column_name, '<?xml version="1.0" encoding="UTF-8"?>', '')).value ('(APIDATA/TRADE/#Action)[1]', 'varchar(100)')

I ran into the same issue with special characters and XML. Below is an example of what I did to resolve the problem with working code that you will need to modify for your DB.
The only thing I needed C# to handle for me was the single quote. C# will need to change the single quote to &apos; before sending it as a CSV list, if not it will fail.
Hope this helps..
/**************************************************************************************
**************************************************************************************
***
*** This is to demonstrate how to use XML in SQL statements.
*** C# must send the the list of items in comma seperated values and
*** replace the character Single Quote with &apos; or the SQL statement
*** will fail. This is the only character that SQL can not handle when sent as a
*** string.
***
*** The steps below will explain each part and how it handles special
*** characters in XML and turns them into a temp table.
***
***
**************************************************************************************
**************************************************************************************/
SET ARITHABORT ON
DECLARE #CUST_REF3 AS XML
DECLARE #CSharpString AS NVARCHAR(MAX)
--This is used for when the CSV string is passed in normally.
SET #CSharpString = ISNULL('{0}', '')
--Example of when the CSV string is passed in and it having a special characters.
SET #CSharpString = 'SHOP A, LA WHEEL & BRAKE SHOP, SHOP&apos;s B'
--Example of when nothing is passed in from C#
--SET #CSharpString = ''
--Replaces any special character for preperation of XML formating
SET #CSharpString = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(#CSharpString,'&', '&'),'<', '<'),'>', '>'),'"', '"'),'''', '&apos;')
-- Turn the #CSharpString (CSV) into XML
SET #CUST_REF3 = CAST('<A>'+ NULLIF(REPLACE(#CSharpString, N',', '</A><A>'), '') + '</A>' AS XML)
--Display the converted XML list
SELECT #CUST_REF3
--Converts the XML nodes into a temp table. Make sure the data type is set correctly for the data being received.
SELECT dbo.Trim(CUST_REF3.value('.','nchar(22)')) AS [CUST_REF3]
INTO #XML_List
FROM #CUST_REF3.nodes('/A') AS x(CUST_REF3)
--Display what Converted list
SELECT * FROM #XML_List
--example of output from the C# String
SELECT USER_DOC, CUST_REF3
FROM dbo.WO_HDR
WHERE
--This matches the list of items sent from C#
((SELECT TOP(1) x.CUST_REF3
FROM #XML_List x
WHERE x.CUST_REF3 = dbo.WO_HDR.CUST_REF3) IS NOT NULL OR
--If the user did not select anything, do not filter
#CSharpString = '')
--Dispose of temp table
IF OBJECT_ID('tempdb..#XML_List') IS NOT NULL
DROP TABLE #XML_List
/**********************************************************************************************************************************************************
--Summerized code to use:
SET ARITHABORT ON
DECLARE #CUST_REF3 AS XML
DECLARE #CSharpString AS NVARCHAR(MAX)
SET #CSharpString = ISNULL('{0}', '')
SET #CSharpString = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(#CSharpString,'&', '&'),'<', '<'),'>', '>'),'"', '"'),'''', '&apos;')
SET #CUST_REF3 = CAST('<A>'+ NULLIF(REPLACE(#CSharpString, N',', '</A><A>'), '') + '</A>' AS XML)
SELECT dbo.Trim(CUST_REF3.value('.','nchar(22)')) AS [CUST_REF3] INTO #XML_List FROM #CUST_REF3.nodes('/A') AS x(CUST_REF3)
--Add this scring to every WHERE statment you want this filter to be used.
--((SELECT TOP(1) x.CUST_REF3 FROM #XML_List x WHERE x.CUST_REF3 = dbo.WO_HDR.CUST_REF3) IS NOT NULL OR #CSharpString = '')
IF OBJECT_ID('tempdb..#XML_List') IS NOT NULL DROP TABLE #XML_List
**********************************************************************************************************************************************************/

Related

How to add additional XML node on top of my SQL generated XML

I have generated XML from a SQL Server FOR XML PATH statement as shown here:
USE MySQLDB
SELECT *
FROM BillTable
FOR XML PATH ('BillAdd'), ROOT ('BillAddRq')
And this is the result:
<BillAddRq>
<BillAdd>
<TxnID>2432-1071510295</TxnID>
<TimeCreated>2003-12-16T01:44:55</TimeCreated>
<TimeModified>2015-12-15T22:38:33</TimeModified>
<EditSequence>1450190313</EditSequence>
<TxnNumber>413</TxnNumber>
<VendorRef_ListID>E0000-933272656</VendorRef_ListID>
<VendorRef_FullName>Timberloft Lumber</VendorRef_FullName>
<APAccountRef_ListID>C0000-933270541</APAccountRef_ListID>
<APAccountRef_FullName>Accounts Payable</APAccountRef_FullName>
<TxnDate>2016-12-01T00:00:00</TxnDate>
<DueDate>2017-12-31T00:00:00</DueDate>
<AmountDue>80.50000</AmountDue>
<TermsRef_ListID>50000-933272659</TermsRef_ListID>
<TermsRef_FullName>1% 10 Net 30</TermsRef_FullName>
<IsPaid>0</IsPaid>
</BillAdd>
<BillAdd>
<TxnID>243A-1071510389</TxnID>
<TimeCreated>2003-12-16T01:46:29</TimeCreated>
<TimeModified>2015-12-15T22:38:33</TimeModified>
<EditSequence>1450190313</EditSequence>
<TxnNumber>414</TxnNumber>
<VendorRef_ListID>C0000-933272656</VendorRef_ListID>
<VendorRef_FullName>Perry Windows & Doors</VendorRef_FullName>
<APAccountRef_ListID>C0000-933270541</APAccountRef_ListID>
<APAccountRef_FullName>Accounts Payable</APAccountRef_FullName>
<TxnDate>2016-12-02T00:00:00</TxnDate>
<DueDate>2018-01-01T00:00:00</DueDate>
<AmountDue>50.00000</AmountDue>
<TermsRef_ListID>10000-933272658</TermsRef_ListID>
<TermsRef_FullName>Net 30</TermsRef_FullName>
<IsPaid>0</IsPaid>
</BillAdd>
</BillAddRq>
Now, I'd like to encapsulate the above with these nodes:
<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="15.0"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
//above generated xml//
</QBXMLMsgsRq>
</QBXML>
How will I achieve this in a SQL Query I created above?
I am new to SQL Server and XML. I am trying to generate this XML directly from my database and vice versa to make it more efficient and faster — let my SQL directly communicate with XML.
ATTEMPT 1:
USE MySQLDB;
GO
DECLARE #myDoc XML;
SET #myDoc = '<QBXML>
<QBXMLMsgsRq onError="stopOnError">
</QBXMLMsgsRq>
</QBXML>';
SET #myDoc.modify('
insert
-- instead of inserting string here.. I would like to insert here the query I made above
into (/QBXML/QBXMLMsgsRq)[1]');
SELECT #myDoc;
ATTEMPT 2:
USE MySQLDB;
GO
DECLARE #myDoc XML;
SET #myDoc = '<QBXML>
<QBXMLMsgsRq onError="stopOnError">
</QBXMLMsgsRq>
</QBXML>';
DECLARE #qry XML;
SET #qry = (SELECT * FROM BillTable FOR XML PATH ('BillAdd'), ROOT ('BillAddRq'));
-- SELECT #qry;
SET #myDoc.modify('insert #qry
into (/QBXML/QBXMLMsgsRq)[1]');
SELECT #myDoc;
There are many ways to construct your XML result, consider the following three alternatives...
Use XML.modify() to insert the BillTable XML into an XML scalar variable (which includes the ?qbxml XML processing instruction):
declare #BillTableXml xml = (
select *
from BillTable
for xml path('BillAdd'), root('BillAddRq')
);
declare #myDoc xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="15.0"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
</QBXMLMsgsRq>
</QBXML>';
set #myDoc.modify('
insert sql:variable("#BillTableXml")
into (/QBXML/QBXMLMsgsRq)[1]
');
select #myDoc as Result;
Use a nested query to construct the entire XML result (which does not, however, include the ?qbxml XML processing instruction):
select
'stopOnError' as [QBXML/QBXMLMsgsRq/#onError],
(
select *
from BillTable
for xml path('BillAdd'), root('BillAddRq'), type
) as [QBXML/QBXMLMsgsRq]
for xml path('');
Or use an XQuery to construct the entire XML result (which also includes the ?qbxml XML processing instruction):
select BillTableXml.query('
<?qbxml version="15.0"?>,
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
{ /BillAddRq }
</QBXMLMsgsRq>
</QBXML>
') as Result
from (
select *
from BillTable
for xml path('BillAdd'), root('BillAddRq'), type
) Data (BillTableXml);

Convert an XML UTF-8 encoded string to XML datatype in SQL Server

Converting an XML string using CAST( AS XML) works as expected in many scenarios, but fail with an error "illegal xml character" if the string contains accented chars.
This example fails with error "XML parsing: line 2, character 8, illegal xml character":
declare #Text VARCHAR(max) =
'<?xml version="1.0" encoding="UTF-8"?>
<ROOT>níveis porém alocação</ROOT>'
select CAST(#Text AS XML)
According to XML Specification all of them are legal XML chars, but replacing accented chars with an 'X' char will result in a sucessfull CAST:
declare #MessageText VARCHAR(max) =
'<?xml version="1.0" encoding="UTF-8"?>
<ROOT>nXveis porXm alocaXXo</ROOT>'
select CAST(#MessageText AS XML)
Result: <ROOT>nXveis porXm alocaXXo</ROOT>
Moreover, the same XML but UTF-16 encoded, inexplicably works:
declare #MessageText NVARCHAR(max) =
'<?xml version="1.0" encoding="UTF-16"?>
<ROOT>níveis porém alocação</ROOT>'
select CAST(#MessageText AS XML)
Result: <ROOT>níveis porém alocação</ROOT>
Are those chars illegal in UTF-8? Or there is a better way to convert into an XML datatype?
SQL Server strips any XML Declaration prolog internally for XML data type and uses UTF-16 encoding. Here is how to handle correctly your use case.
SQL
-- Method #1
DECLARE #Text NVARCHAR(MAX) = N'<ROOT>níveis porém alocação</ROOT>';
SELECT CAST(#Text AS XML);
-- Method #2
DECLARE #MessageText NVARCHAR(MAX) =
'<?xml version="1.0" encoding="UTF-16"?>
<ROOT>níveis porém alocação</ROOT>';
SELECT CAST(#MessageText AS XML);

Passing irregular xml file to the stored procedure

I have a sample xml as follows. I am trying to get all or specific data and then insert into the my sql table which has the same columns representing the values coming from xml. I looked through some solutions but the xml files are not formatted like I have in here. Can you help me?
<?xml version="1.0" encoding="UTF-8" standalone="true"?>
<VehicleStatusResponse xmlns:ns2=
"http://fms-standard.com/rfms/v1.0.0/xsd/common/position" xmlns="http://fms-standard.com/rfms/v1.0.0/xsd/status">
<VehicleStatus>
<VIN>VF254ANA735752628</VIN>
<TriggerType>TIMER</TriggerType>
<CreatedDateTime>2014-09-08T09:30:20</CreatedDateTime>
<ReceivedDateTime>2014-09-08T09:30:57</ReceivedDateTime>
<GNSSPosition>
<ns2:Latitude>49.18557</ns2:Latitude>
<ns2:Longitude>11.18557</ns2:Longitude>
<ns2:Heading>33</ns2:Heading>
<ns2:Altitude>500</ns2:Altitude>
<ns2:Speed>16.4</ns2:Speed>
<ns2:PositionDateTime>2014-09-08T09:30:20</ns2:PositionDateTime>
</GNSSPosition>
<WheelBasedSpeed>16.07</WheelBasedSpeed>
<TachographSpeed>15.83</TachographSpeed>
<HRTotalVehicleDistance>817.5</HRTotalVehicleDistance>
<EngineTotalFuelUsed>575</EngineTotalFuelUsed>
<FuelLevel1>83</FuelLevel1>
<CatalystFuelLevel>88.48</CatalystFuelLevel>
<GrossCombinationVehicleWeight>10000</GrossCombinationVehicleWeight>
</VehicleStatus>
</VehicleStatusResponse>
You can use an XML type and XML methods if you remove or modify the declaration. The SQL Server XML type only supports UCS-2 encoding and doesn't recognize "standalone". The example below uses string manipulation to tweak the declaration. You'll need to change the data types according to your actual column types and should specify an explicit column list on the INSERT statement. I omitted that in this example only because I didn't want to assume your actual table columns matched the element names in the XML.
DECLARE #xml xml;
DECLARE #xmlString nvarchar(MAX) = N'<?xml version="1.0" encoding="UTF-8" standalone="true"?>
<VehicleStatusResponse xmlns:ns2=
"http://fms-standard.com/rfms/v1.0.0/xsd/common/position" xmlns="http://fms-standard.com/rfms/v1.0.0/xsd/status">
<VehicleStatus>
<VIN>VF254ANA735752628</VIN>
<TriggerType>TIMER</TriggerType>
<CreatedDateTime>2014-09-08T09:30:20</CreatedDateTime>
<ReceivedDateTime>2014-09-08T09:30:57</ReceivedDateTime>
<GNSSPosition>
<ns2:Latitude>49.18557</ns2:Latitude>
<ns2:Longitude>11.18557</ns2:Longitude>
<ns2:Heading>33</ns2:Heading>
<ns2:Altitude>500</ns2:Altitude>
<ns2:Speed>16.4</ns2:Speed>
<ns2:PositionDateTime>2014-09-08T09:30:20</ns2:PositionDateTime>
</GNSSPosition>
<WheelBasedSpeed>16.07</WheelBasedSpeed>
<TachographSpeed>15.83</TachographSpeed>
<HRTotalVehicleDistance>817.5</HRTotalVehicleDistance>
<EngineTotalFuelUsed>575</EngineTotalFuelUsed>
<FuelLevel1>83</FuelLevel1>
<CatalystFuelLevel>88.48</CatalystFuelLevel>
<GrossCombinationVehicleWeight>10000</GrossCombinationVehicleWeight>
</VehicleStatus>
</VehicleStatusResponse>';
SET #xmlString = REPLACE(#xmlString, 'encoding="UTF-8"', 'encoding="UCS-2"');
SET #xmlString = REPLACE(#xmlString, 'standalone="true"', '');
SET #xml = #xmlString;
WITH XMLNAMESPACES (
DEFAULT 'http://fms-standard.com/rfms/v1.0.0/xsd/status'
,'http://fms-standard.com/rfms/v1.0.0/xsd/common/position' AS ns2
)
INSERT INTO dbo.YourTable
SELECT
#xml.value('(/VehicleStatusResponse/VehicleStatus/VIN)[1]', 'varchar(50)')
, #xml.value('(/VehicleStatusResponse/VehicleStatus/TriggerType)[1]', 'varchar(50)')
, #xml.value('(/VehicleStatusResponse/VehicleStatus/CreatedDateTime)[1]', 'datetime2(3)')
, #xml.value('(/VehicleStatusResponse/VehicleStatus/ReceivedDateTime)[1]', 'datetime2(3)')
, #xml.value('(/VehicleStatusResponse/VehicleStatus/GNSSPosition/ns2:Latitude)[1]', 'decimal(8,5)')
, #xml.value('(/VehicleStatusResponse/VehicleStatus/GNSSPosition/ns2:Longitude)[1]', 'decimal(8,5)')
, #xml.value('(/VehicleStatusResponse/VehicleStatus/GNSSPosition/ns2:Heading)[1]', 'int')
, #xml.value('(/VehicleStatusResponse/VehicleStatus/GNSSPosition/ns2:Altitude)[1]', 'int')
, #xml.value('(/VehicleStatusResponse/VehicleStatus/GNSSPosition/ns2:Speed)[1]', 'decimal(8,3)')
, #xml.value('(/VehicleStatusResponse/VehicleStatus/GNSSPosition/ns2:PositionDateTime)[1]', 'datetime2(3)')
, #xml.value('(/VehicleStatusResponse/VehicleStatus/WheelBasedSpeed)[1]', 'decimal(8,3)')
, #xml.value('(/VehicleStatusResponse/VehicleStatus/TachographSpeed)[1]', 'decimal(8,3)')
, #xml.value('(/VehicleStatusResponse/VehicleStatus/HRTotalVehicleDistance)[1]', 'decimal(8,3)')
, #xml.value('(/VehicleStatusResponse/VehicleStatus/EngineTotalFuelUsed)[1]', 'int')
, #xml.value('(/VehicleStatusResponse/VehicleStatus/CatalystFuelLevel)[1]', 'decimal(8,3)')
, #xml.value('(/VehicleStatusResponse/VehicleStatus/GrossCombinationVehicleWeight)[1]', 'int');
First of all you need to get your value into a declare variable of type XML or into an XML-typed data table column. As your XML contains namespaces you have to declare them in a WITH XMLNAMESPACES first. You might use wildcard syntax (*:), but its better to be as specific as possible.
The .nodes() call navigates to the Level of <VehicleStatus>. All elements below are simply 1:1 and easy to read...
You can try it like this:
DECLARE #xml XML=
N'<VehicleStatusResponse xmlns:ns2=
"http://fms-standard.com/rfms/v1.0.0/xsd/common/position" xmlns="http://fms-standard.com/rfms/v1.0.0/xsd/status">
<VehicleStatus>
<VIN>VF254ANA735752628</VIN>
<TriggerType>TIMER</TriggerType>
<CreatedDateTime>2014-09-08T09:30:20</CreatedDateTime>
<ReceivedDateTime>2014-09-08T09:30:57</ReceivedDateTime>
<GNSSPosition>
<ns2:Latitude>49.18557</ns2:Latitude>
<ns2:Longitude>11.18557</ns2:Longitude>
<ns2:Heading>33</ns2:Heading>
<ns2:Altitude>500</ns2:Altitude>
<ns2:Speed>16.4</ns2:Speed>
<ns2:PositionDateTime>2014-09-08T09:30:20</ns2:PositionDateTime>
</GNSSPosition>
<WheelBasedSpeed>16.07</WheelBasedSpeed>
<TachographSpeed>15.83</TachographSpeed>
<HRTotalVehicleDistance>817.5</HRTotalVehicleDistance>
<EngineTotalFuelUsed>575</EngineTotalFuelUsed>
<FuelLevel1>83</FuelLevel1>
<CatalystFuelLevel>88.48</CatalystFuelLevel>
<GrossCombinationVehicleWeight>10000</GrossCombinationVehicleWeight>
</VehicleStatus>
</VehicleStatusResponse>';
--This is the query
WITH XMLNAMESPACES(DEFAULT 'http://fms-standard.com/rfms/v1.0.0/xsd/status'
,'http://fms-standard.com/rfms/v1.0.0/xsd/common/position' AS ns2)
SELECT vs.value('VIN[1]','nvarchar(max)') AS VehicleStatus_VIN
,vs.value('TriggerType[1]','nvarchar(max)') AS VehicleStatus_TriggerType
,vs.value('CreatedDateTime[1]','datetime') AS VehicleStatus_CreatedDateTime
,vs.value('ReceivedDateTime[1]','datetime') AS VehicleStatus_ReceivedDateTime
,vs.value('(GNSSPosition/ns2:Latitude)[1]','decimal(14,6)') AS VehicleStatus_GNSSPosition_Latitude
,vs.value('(GNSSPosition/ns2:Longitude)[1]','decimal(14,6)') AS VehicleStatus_GNSSPosition_Longitude
/*other columns follow the same pattern*/
FROM #xml.nodes('/VehicleStatusResponse/VehicleStatus') AS A(vs)
update: insert into a table
Easiest was to wrap this call as CTE like
WITH XMLNAMESPACES(...)
,DerivedTableCTE AS
(
The query here
)
INSERT INTO YourTable (col1, col2, col3, ...)
SELECT col1, col2, col3, ...
FROM DerivedTableCTE

Retrieve all XML elements with the same prefix in SQL Server

I have an XML file in a format similar to:
<XML>
<Field1>100</Field1>
<Field2>200</Field2>
<Field3>300</Field3>
<Test>400</Test>
</XML>
I need to write a query that will get all of the element values that start with Field. So given the XML above the result should be
FieldVal
--------
100
200
300
I've tried the following but it does not work:
Select
xc.value('text()', 'int')
From
#XMLData.nodes('/XML/[starts-with(name(), ''Field'')]') As xt(xc)
NOTE: I am well aware that this task could be easily done if I reformatted my XML but unfortunately I have no control over the format of the XML.
One way is
declare #XMLData xml ='<XML>
<Field1>100</Field1>
<Field2>200</Field2>
<Field3>300</Field3>
<Test>400</Test>
</XML>'
Select
xc.value('.', 'int')
From #XMLData.nodes('/XML/*') As xt(xc)
WHERE xc.value('local-name(.)', 'varchar(50)') LIKE 'Field%'
Prefix name with special character and check contains instead.
declare #x xml ='<XML>
<Field1>100</Field1>
<Field2>200</Field2>
<Field3>300</Field3>
<Test>400</Test>
</XML>';
select t.n.value('.','varchar(100)')
from #x.nodes ('XML/*[contains(concat("$",local-name()),"$Field")]') t(n);
I think it's this what you are looking for:
DECLARE #xml XML=
'<XML>
<Field1>100</Field1>
<Field2>200</Field2>
<Field3>300</Field3>
<Test>400</Test>
</XML>';
SELECT Fld.value('.','int') AS FieldOnly
FROM #xml.nodes('/XML/*[substring(local-name(.),1,5)="Field"]') AS A(Fld)
Just because of the discussion in comments:
DECLARE #fldName VARCHAR(100)='Field';
SELECT Fld.value('.','int') AS FieldOnly
FROM #xml.nodes('/XML/*[substring(local-name(.),1,string-length(sql:variable("#fldName")))=sql:variable("#fldName")]') AS A(Fld)
Change the first line to "Test" (case sensitive!), and you'd get just the one row with 400...

Exporting a xml document from sql 2008

All
I have very little experience of xml, so please be gentle.
The situation is we use an application called dataswitch to take xml and process it into our ERP system via business objects.
The output I am trying to recreate is as follows from a sample xml document.
**<?xml version="1.0" encoding="Windows-1252" ?>
- <IssueDetails Language="05" CssStyle="" DecFormat="1" DateFormat="01" Role="01" Version="6.0.000">**
- <Item>
<Job>00000121</Job>
<NonStocked>N</NonStocked>
<Warehouse>RM</Warehouse>
<StockCode>BBMB100</StockCode>
<Line>00</Line>
<QuantityToIssue>1.000</QuantityToIssue>
</Item>
</IssueDetails>
So far I have worked on the For xml Path method to build my query and used the sp from Phil Factor to write the output
So far I have been successful creating an xml document which opens in the browser (many tries required!)
This is the output I have managed to create, please note the top lines are different
**<IssueDetails xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">**
- <Item>
<Job>00044816</Job>
<NonStocked>N</NonStocked>
<Warehouse>C2</Warehouse>
<StockCode>FG00707</StockCode>
<Line>00</Line>
<QuantityToIssue>400.000000000</QuantityToIssue>
</Item>
- <Item>
<Job>00044816</Job>
<NonStocked>N</NonStocked>
<Warehouse>C2</Warehouse>
<StockCode>FG00707</StockCode>
<Line>00</Line>
<QuantityToIssue>10.000000000</QuantityToIssue>
</Item>
</IssueDetails>
So my question is how do I get the top line in my output to be the same as the sample output?
My procedure is listed below
Declare
#XML_1 varchar (max),
#myXML varchar(max),
#myFile varchar (30),
#Path varchar (100)
set #XML_1=''
set #myFile ='MaterialIssuesTest.xml'
set #Path='D:\Temp\'
--Query database for materials
Set #XML_1 =#XML_1 + ( SELECT WJM.[Job]
,Case when WJM.[Warehouse]='**' then 'Y' else 'N' end as NonStocked
,WJM.[Warehouse]
,rtrim(LP.StockCode) as StockCode
,WJM.[Line]
,[UnitQtyReqd]*LP.LQtyComplete as QuantityToIssue
FROM [SysproCompanyR].[dbo].[WipJobAllMat] WJM
inner join CHC_Production.LabPostsAtMileOps LP On WJM.Job=LP.Job
Where WJM.Job in ('00044816')and (WJM.OperationOffset > LP.PrevOp
and WJM.OperationOffset<LP.LOperation)
FOR XML Path ('Item'),ROOT ('IssueDetails'), ELEMENTS XSINIL
)
set #myXML = LTRIM(rtrim(#XML_1))
--Debug print xml
Print #myXML
--Output xml to document
execute dbo.spWriteStringToFile #myXML, #Path, #myFile
GO
To get you first line, which is a child element of the main body you need to do a sub query like what I have done below. To get the attributes you need to name them with the # symbol, again in my example (formatting changes to aid me setting it out!):
SET #XML_1 =#XML_1 +
(
SELECT WJM.[Job],
(
SELECT '' AS '#Language',
'' AS '#CssStyle',
'' AS '#DecFormat',
'' AS '#DateFormat',
'' AS '#Role',
'' AS '#Version'
FROM YOURTABLENAME YTN
WHERE YTN.[SOMEFIELD] = WJM.[SOMEFIELD]
FOR XML PATH(''), TYPE
) AS 'IssueDetails'
,Case when WJM.[Warehouse]='**' then 'Y' else 'N' end as NonStocked
,WJM.[Warehouse]
,rtrim(LP.StockCode) as StockCode
,WJM.[Line]
,[UnitQtyReqd]*LP.LQtyComplete as QuantityToIssue
FROM [SysproCompanyR].[dbo].[WipJobAllMat] WJM
INNER JOIN CHC_Production.LabPostsAtMileOps LP ON WJM.Job = LP.Job
WHERE WJM.Job IN ('00044816') AND (WJM.OperationOffset > LP.PrevOp
AND WJM.OperationOffset<LP.LOperation)
FOR XML Path ('Item'), ROOT ('IssueDetails'), ELEMENTS XSINIL
)
I don't know where the data is coming from, so you will have to fill in the table name and the WHERE clause to join it to the data that you already have. That is assuming the data is a child of the data that you have already provided.
Bare in mind the syntax might not be quite correct as I am doing this from memory and there are several different variations to get this result.