I need to parse some XML to insert into a table, but my mid level node names can be one of two values <Image> or <Video>. I have an 'after insert' trigger to do this and here is my attempt, however it is not working. The area of interest is/are the CASE statements toward the bottom.
USE [cims]
GO
/****** Object: Trigger [dbo].[tr_XML_Insert] Script Date: 07/08/2014 16:52:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[tr_XML_Insert]
ON [dbo].[ContainerXML]
AFTER INSERT
AS
BEGIN
IF @@ROWCOUNT = 0
RETURN
SET NOCOUNT ON
IF EXISTS(SELECT [XMLData] FROM INSERTED)
BEGIN
DECLARE @XML XML
SELECT @XML = XMLData FROM [inserted]
INSERT INTO [dbo].[ContainerImage]
(
CaptureDeviceCDIFID, CaptureDeviceName, Lat, Lon, DodAAC, OCR_Equipment, MOD_Equipment,
TypeCode, SideImageComments, BackImageComments, SideImageCaptureDate, SideImage,
BackImageCaptureDate, BackImage,
RecordCreateDate
)
SELECT
col.value('PCMU[1]/@cdifid[1]', 'NVARCHAR(15)'),
col.value('PCMU[1]/@Name[1]', 'NVARCHAR(100)'),
col.value('Location[1]/@lat[1]', '[DECIMAL](18,9)'),
col.value('Location[1]/@lon[1]', '[DECIMAL](18,9)'),
col.value('Location[1]/@DoDAAC[1]', 'NVARCHAR(10)'),
REPLACE(col.value('BIC[1]/@ISOCode[1]', 'NVARCHAR(12)'), ' ', ''),
REPLACE(col.value('BIC[1]/@ISOCode[1]', 'NVARCHAR(12)'), ' ', ''),
col.value('BIC[1]/@TypeCode[1]', 'NVARCHAR(10)'),
col.value('BIC[1]/@UserText1[1]', 'NVARCHAR(255)'),
col.value('BIC[1]/@UserText2[1]', 'NVARCHAR(255)'),
CASE xmldata.col.value('local-name(/*[1])','varchar(20)')
WHEN 'Image' THEN col.value('Image[1]/@imagetime[1]', 'DATETIME')
WHEN 'Video' THEN col.value('Video[1]/@time[1]', 'DATETIME')
END,
CASE xmldata.col.value('local-name(/*[1])','varchar(20)')
WHEN 'Image' THEN col.value('Image[1]/@imageData[1]', 'VARBINARY(MAX)')
WHEN 'Video' THEN col.value('Video[1]/@videoData[1]', 'VARBINARY(MAX)')
END,
CASE xmldata.col.value('local-name(/*[1])','varchar(20)')
WHEN 'Image' THEN col.value('Image[2]/@imagetime[1]', 'DATETIME')
WHEN 'Video' THEN col.value('Video[2]/@time[1]', 'DATETIME')
END,
CASE xmldata.col.value('local-name(/*[1])','varchar(20)')
WHEN 'Image' THEN col.value('Image[2]/@imageData[1]', 'VARBINARY(MAX)')
WHEN 'Video' THEN col.value('Video[2]/@videoData[1]', 'VARBINARY(MAX)')
END,
GETDATE()
FROM @XML.nodes('//Containers/Container') as xmldata(col)
END
END
Here are the 2 format for XML files - I can easily do one or the other, I am looking for a way to do it within the same code. I essentially want everything in the XML, I just do not know how to say "if node name == Image, get these fields, else if node name == Video, get these fields
<Containers>
<Container>
<PCMU cdifid="81.135.189.71" Name="Test PCMU1" />
<Location lat="38.35688" lon="-77.45752"
DoDAAC="TODO??" />
<BIC time="2014-06-20T15:11:07"
idStatus="OK"
ISOCode="(null)"
TypeCode="0x0"
UserText1="??"
UserText2="??" />
<Video view="Container Side"
time="2014-06-20T15:11:07"
videoData="big chunk of base64 data"/>
<Video view="Container Rear"
time="2014-06-20T15:11:07"
videoData="big chunk of base64 data" />
</Container>
</Containers>
<Containers>
<Container>
<PCMU cdifid="81.135.189.71" Name="Test PCMU1" />
<Location lat="38.35688" lon="-77.45752"
DoDAAC="TODO??" />
<BIC time="2014-06-20T15:11:07"
idStatus="OK"
ISOCode="(null)"
TypeCode="0x0"
UserText1="??"
UserText2="??" />
<Image view="Container Side"
imageTime="2014-06-20T15:11:07"
imageData="big chunk of base64 data"/>
<Image view="Container Rear"
imageTime="2014-06-20T15:11:07"
imageData="big chunk of base64 data" />
</Container>
</Containers>
insertedwill have multiple rows. Instead of assigning the XML to a variable you should useinsertedin the query with across applyonXMLData.nodes(...)...