带有子元素的 CDATA
CDATA with Child elements
我想要带有 MakeType 子集的结果。
现在我得到了整个块而不是 MakeType 的元素。
当 XML 解析类型、系列和 class 标签时,应该为它们创建一个元素。这是 SQL 服务器标准 2017.And 我真的不知道 CDATA xml 风格,不会使用它,但供应商需要 CDATA 类型。
---Create Temp Table
declare @RepCar table
(
[Name] varchar(10),
[Make] varchar(10),
[Model] varchar(10),
[Price] money,
[Type] varchar(10),
[Series] varchar(10),
[Class] Varchar(10)
);
insert into @RepCar
(
Name, Make, Model, Price, Type, Series, Class
)
values
('Car1', 'Make1', 'Model1', 100, 'Type1', 'IS', 'Sedan'),
('Car1', 'Make1', 'Model1', 100, 'Type1', 'LS' , 'Sport'),
('Car2', 'Make2', 'Model2', 200, 'Type2', 'M3' , 'Sport'),
('Car3', 'Make3', 'Model3', 300, 'Type3','GS350','Sedan');
--Declare Variables
DECLARE @TransactionId NVARCHAR(100)
DECLARE @TransactionDateTime DATETIME
--Setting Variable
SET @TransactionId= (SELECT CONVERT(VARCHAR, CURRENT_TRANSACTION_ID()))
SET @TransactionDateTime= GETDATE()
--Create the XML
select 1 AS Tag,
0 AS Parent,
'CollectSamplingData' as 'Message!1!TransactionType!cdata',
@TransactionId as 'Message!1!TransactionID!cdata',
@TransactionDateTime as 'Message!1!TransactionDate!cdata',
[Name] as 'Message!1!CName!cdata',
[Make] as 'Message!1!MakeCar!cdata',
[Model] as 'Message!1!MakeModel!cdata',
[Price] as 'Message!1!DataValue!cdata',
[Type] as 'Message!1!MakeType!cdata' ,
-----This is the SQL that is'nt working.
( select
1 AS Tag,
0 AS Parent,
[Series] as 'Message!2!MakeSeries!cdata',
[Class] as 'Message!2!MakeClass!cdata'
from @RepCar
FOR XML EXPLICIT
)
from @RepCar
FOR XML EXPLICIT, ROOT('Message');
结果应该看起来像 this.When 代码确实看到 MakeType 应该有 Series 和下面的 class 作为子元素。这些是所需的输出 XML
<Message>
<Message>
<TransactionType><![CDATA[CollectSamplingData]]></TransactionType>
<TransactionID><![CDATA[1482282230]]></TransactionID>
<TransactionDate><![CDATA[2020-02-03T11:05:17.340]]></TransactionDate>
<CName><![CDATA[Car1]]></CName>
<MakeCar><![CDATA[Make1]]></MakeCar>
<MakeModel><![CDATA[Model1]]></MakeModel>
<DataValue><![CDATA[100.0000]]></DataValue>
<MakeType><![CDATA[Type1]]>
<Series><![CDATA[IS]></Series>
<Class><![CDATA[Sedan]]></Class>
<Series><![CDATA[LS]></Series>
<Class><![CDATA[Sport]]></Class>
<Series><![CDATA[M3]></Series>
<Class><![CDATA[Sport]]></Class>
<Series><![CDATA[GS350]></Series>
<Class><![CDATA[Sedan]]></Class>>
</MakeType>
</Message>
我努力通过使用 FOR XML EXPLICIT
来生产您需要的东西。最终,我恢复使用 XQuery FLWOR 表达式。请记住 SQL 服务器 XML 数据类型不能包含 CDATA
部分。您需要使用 NVARCHAR(MAX)
数据类型。在这里查看:如何在 SQL XML 中使用 CDATA
SQL
-- DDL and sample data population, start
DECLARE @RepCar TABLE
(
[Name] VARCHAR(10),
[Make] VARCHAR(10),
[Model] VARCHAR(10),
[Price] MONEY,
[Type] VARCHAR(10),
[Series] VARCHAR(10),
[Class] VARCHAR(10)
);
INSERT INTO @RepCar
(
Name,
Make,
Model,
Price,
Type,
Series,
Class
)
VALUES
('Car1', 'Make1', 'Model1', 100, 'Type1', 'IS', 'Sedan'),
('Car1', 'Make1', 'Model1', 100, 'Type1', 'LS', 'Sport'),
('Car2', 'Make2', 'Model2', 200, 'Type2', 'M3', 'Sport'),
('Car3', 'Make3', 'Model3', 300, 'Type3', 'GS350', 'Sedan');
-- DDL and sample data population, end
--Declare Variables
DECLARE @TransactionId NVARCHAR(100) = CURRENT_TRANSACTION_ID();
DECLARE @TransactionDateTime DATETIME = GETDATE();
DECLARE @lt NCHAR(4) = '<'
, @gt NCHAR(4) = '>';
SELECT REPLACE(REPLACE(TRY_CAST((SELECT 'CollectSamplingData' AS [TransactionType]
, @TransactionId AS [TransactionID]
, @TransactionDateTime AS [TransactionDate]
, *
FROM @RepCar
FOR XML PATH('r'), TYPE, ROOT('root')).query('<Messages><Message>
{
for $x in /root/r[1]
return (<TransactionType>{concat("<![CDATA[", data($x/TransactionType[1]), "]]>")}</TransactionType>,
<TransactionID>{concat("<![CDATA[", data($x/TransactionID[1]), "]]>")}</TransactionID>,
<TransactionDate>{concat("<![CDATA[", data($x/TransactionDate[1]), "]]>")}</TransactionDate>,
<CName>{concat("<![CDATA[", data($x/Name[1]), "]]>")}</CName>,
<MakeCar>{concat("<![CDATA[", data($x/Make[1]), "]]>")}</MakeCar>,
<MakeModel>{concat("<![CDATA[", data($x/Model[1]), "]]>")}</MakeModel>,
<DataValue>{concat("<![CDATA[", data($x/Price[1]), "]]>")}</DataValue>,
<MakeType>{concat("<![CDATA[", data($x/Type[1]), "]]>")}
{
for $y in /root/r
return (
<Series>{concat("<![CDATA[", data($y/Series[1]), "]]>")}</Series>,
<Class>{concat("<![CDATA[", data($y/Class[1]), "]]>")}</Class>
)
}
</MakeType>)
}
</Message></Messages>') AS NVARCHAR(MAX)), @lt,'<'), @gt, '>') AS [XML with CDATA sections];
Output
<Messages>
<Message>
<TransactionType><![CDATA[CollectSamplingData]]></TransactionType>
<TransactionID><![CDATA[1149709]]></TransactionID>
<TransactionDate><![CDATA[2020-02-03T16:23:43.020]]></TransactionDate>
<CName><![CDATA[Car1]]></CName>
<MakeCar><![CDATA[Make1]]></MakeCar>
<MakeModel><![CDATA[Model1]]></MakeModel>
<DataValue><![CDATA[100.0000]]></DataValue>
<MakeType><![CDATA[Type1]]>
<Series><![CDATA[IS]]></Series>
<Class><![CDATA[Sedan]]></Class>
<Series><![CDATA[LS]]></Series>
<Class><![CDATA[Sport]]></Class>
<Series><![CDATA[M3]]></Series>
<Class><![CDATA[Sport]]></Class>
<Series><![CDATA[GS350]]></Series>
<Class><![CDATA[Sedan]]></Class>
</MakeType>
</Message>
</Messages>
只是为了比较,我想展示一下当 XQuery 引擎完全支持标准时实现 CDATA 部分是多么容易。下面是使用 cdata-section-elements
序列化参数的 BaseX 9.3.1 实现:要作为 CDATA 输出的元素列表,由空格分隔.
两个元素 <city>
和 <motto>
以简单的声明方式作为 CDATA 部分发出。
XQuery
xquery version "3.1";
declare option output:omit-xml-declaration "no";
declare option output:cdata-section-elements "city motto";
declare context item := document {
<root>
<row>
<state>FL</state>
<motto>In God We Trust</motto>
<city>Miami</city>
</row>
<row>
<state>NJ</state>
<motto>Liberty and Prosperity</motto>
<city>Trenton</city>
</row>
</root>
};
<root>
{
for $r in ./root/row
return $r
}
</root>
Output
<?xml version="1.0" encoding="UTF-8"?>
<root>
<row>
<state>FL</state>
<motto><![CDATA[In God We Trust]]></motto>
<city><![CDATA[Miami]]></city>
</row>
<row>
<state>NJ</state>
<motto><![CDATA[Liberty and Prosperity]]></motto>
<city><![CDATA[Trenton]]></city>
</row>
</root>
我想要带有 MakeType 子集的结果。 现在我得到了整个块而不是 MakeType 的元素。 当 XML 解析类型、系列和 class 标签时,应该为它们创建一个元素。这是 SQL 服务器标准 2017.And 我真的不知道 CDATA xml 风格,不会使用它,但供应商需要 CDATA 类型。
---Create Temp Table
declare @RepCar table
(
[Name] varchar(10),
[Make] varchar(10),
[Model] varchar(10),
[Price] money,
[Type] varchar(10),
[Series] varchar(10),
[Class] Varchar(10)
);
insert into @RepCar
(
Name, Make, Model, Price, Type, Series, Class
)
values
('Car1', 'Make1', 'Model1', 100, 'Type1', 'IS', 'Sedan'),
('Car1', 'Make1', 'Model1', 100, 'Type1', 'LS' , 'Sport'),
('Car2', 'Make2', 'Model2', 200, 'Type2', 'M3' , 'Sport'),
('Car3', 'Make3', 'Model3', 300, 'Type3','GS350','Sedan');
--Declare Variables
DECLARE @TransactionId NVARCHAR(100)
DECLARE @TransactionDateTime DATETIME
--Setting Variable
SET @TransactionId= (SELECT CONVERT(VARCHAR, CURRENT_TRANSACTION_ID()))
SET @TransactionDateTime= GETDATE()
--Create the XML
select 1 AS Tag,
0 AS Parent,
'CollectSamplingData' as 'Message!1!TransactionType!cdata',
@TransactionId as 'Message!1!TransactionID!cdata',
@TransactionDateTime as 'Message!1!TransactionDate!cdata',
[Name] as 'Message!1!CName!cdata',
[Make] as 'Message!1!MakeCar!cdata',
[Model] as 'Message!1!MakeModel!cdata',
[Price] as 'Message!1!DataValue!cdata',
[Type] as 'Message!1!MakeType!cdata' ,
-----This is the SQL that is'nt working.
( select
1 AS Tag,
0 AS Parent,
[Series] as 'Message!2!MakeSeries!cdata',
[Class] as 'Message!2!MakeClass!cdata'
from @RepCar
FOR XML EXPLICIT
)
from @RepCar
FOR XML EXPLICIT, ROOT('Message');
结果应该看起来像 this.When 代码确实看到 MakeType 应该有 Series 和下面的 class 作为子元素。这些是所需的输出 XML
<Message>
<Message>
<TransactionType><![CDATA[CollectSamplingData]]></TransactionType>
<TransactionID><![CDATA[1482282230]]></TransactionID>
<TransactionDate><![CDATA[2020-02-03T11:05:17.340]]></TransactionDate>
<CName><![CDATA[Car1]]></CName>
<MakeCar><![CDATA[Make1]]></MakeCar>
<MakeModel><![CDATA[Model1]]></MakeModel>
<DataValue><![CDATA[100.0000]]></DataValue>
<MakeType><![CDATA[Type1]]>
<Series><![CDATA[IS]></Series>
<Class><![CDATA[Sedan]]></Class>
<Series><![CDATA[LS]></Series>
<Class><![CDATA[Sport]]></Class>
<Series><![CDATA[M3]></Series>
<Class><![CDATA[Sport]]></Class>
<Series><![CDATA[GS350]></Series>
<Class><![CDATA[Sedan]]></Class>>
</MakeType>
</Message>
我努力通过使用 FOR XML EXPLICIT
来生产您需要的东西。最终,我恢复使用 XQuery FLWOR 表达式。请记住 SQL 服务器 XML 数据类型不能包含 CDATA
部分。您需要使用 NVARCHAR(MAX)
数据类型。在这里查看:如何在 SQL XML 中使用 CDATA
SQL
-- DDL and sample data population, start
DECLARE @RepCar TABLE
(
[Name] VARCHAR(10),
[Make] VARCHAR(10),
[Model] VARCHAR(10),
[Price] MONEY,
[Type] VARCHAR(10),
[Series] VARCHAR(10),
[Class] VARCHAR(10)
);
INSERT INTO @RepCar
(
Name,
Make,
Model,
Price,
Type,
Series,
Class
)
VALUES
('Car1', 'Make1', 'Model1', 100, 'Type1', 'IS', 'Sedan'),
('Car1', 'Make1', 'Model1', 100, 'Type1', 'LS', 'Sport'),
('Car2', 'Make2', 'Model2', 200, 'Type2', 'M3', 'Sport'),
('Car3', 'Make3', 'Model3', 300, 'Type3', 'GS350', 'Sedan');
-- DDL and sample data population, end
--Declare Variables
DECLARE @TransactionId NVARCHAR(100) = CURRENT_TRANSACTION_ID();
DECLARE @TransactionDateTime DATETIME = GETDATE();
DECLARE @lt NCHAR(4) = '<'
, @gt NCHAR(4) = '>';
SELECT REPLACE(REPLACE(TRY_CAST((SELECT 'CollectSamplingData' AS [TransactionType]
, @TransactionId AS [TransactionID]
, @TransactionDateTime AS [TransactionDate]
, *
FROM @RepCar
FOR XML PATH('r'), TYPE, ROOT('root')).query('<Messages><Message>
{
for $x in /root/r[1]
return (<TransactionType>{concat("<![CDATA[", data($x/TransactionType[1]), "]]>")}</TransactionType>,
<TransactionID>{concat("<![CDATA[", data($x/TransactionID[1]), "]]>")}</TransactionID>,
<TransactionDate>{concat("<![CDATA[", data($x/TransactionDate[1]), "]]>")}</TransactionDate>,
<CName>{concat("<![CDATA[", data($x/Name[1]), "]]>")}</CName>,
<MakeCar>{concat("<![CDATA[", data($x/Make[1]), "]]>")}</MakeCar>,
<MakeModel>{concat("<![CDATA[", data($x/Model[1]), "]]>")}</MakeModel>,
<DataValue>{concat("<![CDATA[", data($x/Price[1]), "]]>")}</DataValue>,
<MakeType>{concat("<![CDATA[", data($x/Type[1]), "]]>")}
{
for $y in /root/r
return (
<Series>{concat("<![CDATA[", data($y/Series[1]), "]]>")}</Series>,
<Class>{concat("<![CDATA[", data($y/Class[1]), "]]>")}</Class>
)
}
</MakeType>)
}
</Message></Messages>') AS NVARCHAR(MAX)), @lt,'<'), @gt, '>') AS [XML with CDATA sections];
Output
<Messages>
<Message>
<TransactionType><![CDATA[CollectSamplingData]]></TransactionType>
<TransactionID><![CDATA[1149709]]></TransactionID>
<TransactionDate><![CDATA[2020-02-03T16:23:43.020]]></TransactionDate>
<CName><![CDATA[Car1]]></CName>
<MakeCar><![CDATA[Make1]]></MakeCar>
<MakeModel><![CDATA[Model1]]></MakeModel>
<DataValue><![CDATA[100.0000]]></DataValue>
<MakeType><![CDATA[Type1]]>
<Series><![CDATA[IS]]></Series>
<Class><![CDATA[Sedan]]></Class>
<Series><![CDATA[LS]]></Series>
<Class><![CDATA[Sport]]></Class>
<Series><![CDATA[M3]]></Series>
<Class><![CDATA[Sport]]></Class>
<Series><![CDATA[GS350]]></Series>
<Class><![CDATA[Sedan]]></Class>
</MakeType>
</Message>
</Messages>
只是为了比较,我想展示一下当 XQuery 引擎完全支持标准时实现 CDATA 部分是多么容易。下面是使用 cdata-section-elements
序列化参数的 BaseX 9.3.1 实现:要作为 CDATA 输出的元素列表,由空格分隔.
两个元素 <city>
和 <motto>
以简单的声明方式作为 CDATA 部分发出。
XQuery
xquery version "3.1";
declare option output:omit-xml-declaration "no";
declare option output:cdata-section-elements "city motto";
declare context item := document {
<root>
<row>
<state>FL</state>
<motto>In God We Trust</motto>
<city>Miami</city>
</row>
<row>
<state>NJ</state>
<motto>Liberty and Prosperity</motto>
<city>Trenton</city>
</row>
</root>
};
<root>
{
for $r in ./root/row
return $r
}
</root>
Output
<?xml version="1.0" encoding="UTF-8"?>
<root>
<row>
<state>FL</state>
<motto><![CDATA[In God We Trust]]></motto>
<city><![CDATA[Miami]]></city>
</row>
<row>
<state>NJ</state>
<motto><![CDATA[Liberty and Prosperity]]></motto>
<city><![CDATA[Trenton]]></city>
</row>
</root>