- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我有带有多个标签的 XML,需要将一些值连接到一个字符串以进行输出。
这适用于 MS SQL 2012
DECLARE @XML AS XML, @hDoc AS INT
SELECT @XML =
'<offers>
<offer>
<a>AAA1</a>
<param name="B">A1B</param>
<param name="C">A1C</param>
</offer>
<offer>
<a>AAA2</a>
<param name="B">A2B</param>
<param name="C">A2C1&</param>
<param name="C">A2C2<</param>
</offer>
</offers>';
EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML
SELECT a, ParamB, ParamC
FROM OPENXML(@hDoc, 'offers/offer')
WITH
(
a [varchar](50) 'a',
ParamB [varchar](255) 'param[@name="B"]',
ParamC [varchar](255) 'param[@name="C"]'
) as S
EXEC sp_xml_removedocument @hDoc
这段代码的输出:
a |ParamB |ParamC
-----------------------------
AAA1 |A1B |A1C
AAA2 |A2B |A2C1&
我需要:
a |ParamB |ParamC
-----------------------------
AAA1 |A1B |A1C
AAA2 |A2B |A2C1& / A2C2<
"/"- 任何拆分器
更新
这个查询:
DECLARE @XML AS XML, @XML1 AS XML, @hDoc AS INT
DECLARE @delimiter VARCHAR(100)=' / ';
SELECT @XML =
'<offers>
<offer>
<a>AAA1</a>
<param name="B">A1B</param>
<param name="C">A1C</param>
</offer>
<offer>
<a>AAA2</a>
<param name="B">A2B</param>
<param name="C">A2C1<</param>
<param name="C">A2C2&</param>
</offer>
</offers>';
SELECT A.o.value('(a/text())[1]','nvarchar(100)') AS Offer_a
,A.o.query('param[@name="B"]') B
,A.o.query('param[@name="C"]') C
FROM @XML.nodes('/offers/offer') A(o);
实际输出我需要的,只需删除 xml 标签并在参数值之间插入分隔符。
这个查询解决了这个问题:
--Test XML variable equal col C for AAA2 from prev query
SET @XML1 =
'<param name="C">A2C1&</param><param name="C">A2C2<</param>';
select (
select @delimiter + p.o.value('.', 'nvarchar(100)')
from @XML1.nodes('param') p(o)
FOR XML PATH(''),TYPE
/* Use .value to uncomment XML entities e.g. > < etc*/
).value('.','VARCHAR(MAX)')
as C_result
但我不知道如何在以前的 SQL 查询中将其作为 XML 列的子查询。看:dbfiddle
最佳答案
首先:FROM OPENXML
(与准备和删除文件的存储过程一起)已过时,不应再使用。而是使用 native XML methods由 XML 数据类型提供。
像这样尝试:
DECLARE @XML AS XML, @hDoc AS INT
SELECT @XML =
'<offers>
<offer>
<a>AAA1</a>
<param name="B">A1B</param>
<param name="C">A1C</param>
</offer>
<offer>
<a>AAA2</a>
<param name="B">A2B</param>
<param name="C">A2C1</param>
<param name="C">A2C2</param>
</offer>
</offers>';
--查询
WITH cte AS
(
SELECT A.o.value('(a/text())[1]','nvarchar(100)') AS Offer_a
,B.p.value('@name','nvarchar(100)') AS Param_Name
,A.o.query('.') TheOffer
FROM @XML.nodes('/offers/offer') A(o)
CROSS APPLY A.o.nodes('param') B(p)
)
SELECT Offer_a
,MAX(CASE WHEN Param_Name='B' THEN REPLACE(concatParams,' ',' / ') END) AS ParamB
,MAX(CASE WHEN Param_Name='C' THEN REPLACE(concatParams,' ',' / ') END) AS ParamC
FROM cte
CROSS APPLY(SELECT TheOffer.query('data(offer/param[@name=sql:column("Param_Name")]/text())').value('.','nvarchar(max)')) A(concatParams)
GROUP BY Offer_a;
简而言之:
cte 将返回一组 text()
的 <a>
, param/@name
的值和 XML 片段 <offer>
对于对应的<a>
.
魔法 发生在 CROSS APPLY(SELECT ...)
中.此子选择将获取适合当前行的 Param_Name
的参数在 row-wise 调用中。 XQuery 函数 sql:column()
允许将当前行的值引入 XQuery 表达式。
非常重要的是 XQuery 函数 data()
.这将返回此路径中由空格分隔的所有数据。遗憾的是,此功能不允许用户定义分隔符。
因此有一个严重的警告:如果您的参数值包含空格,您将不知道在哪里分隔它们...如果您需要这个,请回来发表评论。
第二个神奇之处是分组聚合。我们按Offer_a
分组并使用 MAX()
允许使用非分组列。这是一种老式的支点方法...
替换将放置斜杠而不是空格(来自 data()
)。
方法一
我们使用 XQuery/FLWOR 遍历节点并在 Xquery 中进行连接。我们可以使用 sql:variable()
将声明的变量引入 XPath 表达式:
DECLARE @delimiter VARCHAR(100)=' / ';
WITH cte AS
(
SELECT A.o.value('(a/text())[1]','nvarchar(100)') AS Offer_a
,B.p.value('@name','nvarchar(100)') AS Param_Name
,A.o.query('.') TheOffer
FROM @XML.nodes('/offers/offer') A(o)
CROSS APPLY A.o.nodes('param') B(p)
)
SELECT Offer_a
,MAX(CASE WHEN Param_Name='B' THEN STUFF(concatParams,1,LEN(@delimiter),'') END) AS ParamB
,MAX(CASE WHEN Param_Name='C' THEN STUFF(concatParams,1,LEN(@delimiter),'') END) AS ParamC
FROM cte
CROSS APPLY(SELECT TheOffer.query('for $p in offer/param[@name=sql:column("Param_Name")]/text()
return <x>{concat(sql:variable("@delimiter"),$p)}</x>
').value('.','nvarchar(max)')) A(concatParams)
GROUP BY Offer_a;
...或方法 2
我们将所有值提取到一个中间集,并使用相关子查询 和 FOR XML
获取连接参数的方法。
WITH cte AS
(
SELECT A.o.value('(a/text())[1]','nvarchar(100)') AS Offer_a
,B.p.value('@name','nvarchar(100)') AS Param_Name
,A.o.query('.') TheOffer
FROM @XML.nodes('/offers/offer') A(o)
CROSS APPLY A.o.nodes('param') B(p)
)
,cte2 AS
(
SELECT cte.Offer_a
,cte.Param_Name
,A.relatedParams.value('text()[1]','nvarchar(100)') AS ParamValue
FROM cte
CROSS APPLY TheOffer.nodes('offer/param[@name=sql:column("Param_Name")]') A(relatedParams)
)
SELECT Offer_a
,MAX(CASE WHEN Param_Name='B' THEN concatParamValues END) AS paramB
,MAX(CASE WHEN Param_Name='C' THEN concatParamValues END) AS paramC
FROM cte2
CROSS APPLY(SELECT STUFF((SELECT DISTINCT CONCAT(@delimiter,ParamValue)
FROM cte2 csq
WHERE csq.Offer_a=cte2.Offer_a
AND csq.Param_Name=cte2.Param_Name
FOR XML PATH('')),1,LEN(@delimiter),'')) A(concatParamValues)
GROUP BY Offer_a;
... 如果您的 XML 可能包含禁止使用的字符,请在末尾使用它
CROSS APPLY(SELECT STUFF((SELECT DISTINCT CONCAT(@delimiter,ParamValue)
FROM cte2 csq
WHERE csq.Offer_a=cte2.Offer_a
AND csq.Param_Name=cte2.Param_Name
FOR XML PATH(''),TYPE).value('.','nvarchar(100)'),1,LEN(@delimiter),'')) A(concatParamValues)
您在评论中提出了一个额外的问题,但我必须承认,我并没有真正得到您所需要的。如果我理解正确,那么您的值(value)观中就有实体。你确实在原则上得到了结果,但这些实体仍然没有被翻译?正确吗?
在我上面的回答中,您已经有了所需的一切。为了清楚起见,一个完整的示例:
DECLARE @delimiter VARCHAR(100)=' / ';
DECLARE @XML AS XML, @hDoc AS INT
SELECT @XML =
'<offers>
<offer>
<a>AAA1</a>
<param name="B">A1B&</param> <!-- Some typical entities -->
<param name="C">A1C<</param>
</offer>
<offer>
<a>AAA2</a>
<param name="B">A2B after space</param> <!-- A case with some spaces -->
<param name="C">A2C1 A</param> <!-- The A is the capital letter A as entity-->
<param name="C">A2C2</param>
</offer>
</offers>';
WITH cte AS
(
SELECT A.o.value('(a/text())[1]','nvarchar(100)') AS Offer_a
,B.p.value('@name','nvarchar(100)') AS Param_Name
,A.o.query('.') TheOffer
FROM @XML.nodes('/offers/offer') A(o)
CROSS APPLY A.o.nodes('param') B(p)
)
,cte2 AS
(
SELECT cte.Offer_a
,cte.Param_Name
,A.relatedParams.value('text()[1]','nvarchar(100)') AS ParamValue
FROM cte
CROSS APPLY TheOffer.nodes('offer/param[@name=sql:column("Param_Name")]') A(relatedParams)
)
SELECT Offer_a
,MAX(CASE WHEN Param_Name='B' THEN concatParamValues END) AS paramB
,MAX(CASE WHEN Param_Name='C' THEN concatParamValues END) AS paramC
FROM cte2
CROSS APPLY(SELECT STUFF((SELECT DISTINCT CONCAT(@delimiter,ParamValue)
FROM cte2 csq
WHERE csq.Offer_a=cte2.Offer_a
AND csq.Param_Name=cte2.Param_Name
FOR XML PATH(''),TYPE).value('.','nvarchar(100)'),1,LEN(@delimiter),'')) A(concatParamValues)
GROUP BY Offer_a;
结果
Offer_a paramB paramC
AAA1 A1B& A1C<
AAA2 A2B after space A2C2 / A2C1 A
上面的“方法 1”会产生相同的结果:
WITH cte AS
(
SELECT A.o.value('(a/text())[1]','nvarchar(100)') AS Offer_a
,B.p.value('@name','nvarchar(100)') AS Param_Name
,A.o.query('.') TheOffer
FROM @XML.nodes('/offers/offer') A(o)
CROSS APPLY A.o.nodes('param') B(p)
)
SELECT Offer_a
,MAX(CASE WHEN Param_Name='B' THEN STUFF(concatParams,1,LEN(@delimiter),'') END) AS ParamB
,MAX(CASE WHEN Param_Name='C' THEN STUFF(concatParams,1,LEN(@delimiter),'') END) AS ParamC
FROM cte
CROSS APPLY(SELECT TheOffer.query('for $p in offer/param[@name=sql:column("Param_Name")]/text()
return <x>{concat(sql:variable("@delimiter"),$p)}</x>
').value('.','nvarchar(max)')) A(concatParams)
GROUP BY Offer_a;
最后,我希望这能解决您的问题...
关于sql-server - 从 openxml 中选择,将多个节点值连接到一个字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57336781/
我的 C# 应用程序使用 OpenXML 创建一个 MSWord 文档,其中已经包含多个表。最后一部分是添加条形图。我找不到这个案例的好例子。 谢谢你的帮助! 我正在从头开始创建文档。从...开始:
我正在使用一个模板文档,该文档使用 CustomXmlBlocks 作为占位符来放置表格和其他信息。我需要能够以某种方式将图像放入其中一个 block 中......即使它首先放入运行中。 图像以字节
我正在以编程方式将 OpenXML 段落添加到 Word 文档中,并且稍后我需要能够将该段落识别为我的段落。关于如何做到这一点有什么想法吗?我尝试插入 XML 注释和扩展属性,但是当您将文档保存在 w
我想使用 openxml 删除一列,我能够清除单元格的内容,但一直无法找到删除列的文档,以便在删除列时向左移动其他单元格。如何使用 openxml 删除列,它将单元格向左移动? 最佳答案 我发现 Op
我找不到任何可以告诉我 txBody 标签中的文本是否带有项目符号的指标,您能否请我确定我应该使用哪个指标来了解文本是项目符号还是普通文本? -谢谢 最佳答案 在 txBody 标签内,您可以查找标签
我目前正在尝试使用 PHPWord 库及其模板系统来处理 docx 文件。我已经找到并更新了这个库的某人(不记得名字,但它并不重要)的路径,该库可以使用表(复制其行,然后在每一行上使用 PHPWord
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: Open Xml and Date format in Excel cell 我正在尝试从 DataGridView
我发现各种元素非常困惑。几乎每个元素似乎都有一个与之关联的“部分”,我不确定它们是如何粘合在一起的。 工作簿工作簿部分工作表工作表部分 我也对 DocumentFormat.OpenXml.Packa
我有一个存储在 Bitmap 对象中的图像,我想将其粘贴到 OpenXML 文档中。我尝试使用 MemoryStream 作为中间步骤,如下所示: ImagePart part = container
我试图理解 OpenXML 电子表格的内部文件内容。在一些文件中,我发现了这个字符串。其他标签具有相同的前缀。标签也可以有前缀 p: w: 等。 你能帮我理解这些前缀在标签中的含义吗? 最佳答案 您可
我的预期结果是: 你好 世界! 但是当我使用以下代码时: MainDocumentPart mainDocumentPart = package.AddMainDo
我需要将多个 .docx 文件收集到一个文件夹中,并将它们“链接”成一个将显示给用户的文档。 现在我已经阅读了 Brian Jones' article虽然听起来很有希望,但我遇到了一个问题。 当我使
我正在使用 OpenXml 生成 Excel 文件,在研究了大量不同的示例代码和 SDK Productivity Tool 后,终于得到了我想要的东西。只有一件事我无法回避。当我使用 Excel 打
我正在使用 openxml 创建 WordProcessingDocuments(工作正常,生成的 word 文档正是我想要的),现在我正在尝试使用 openxml Powertools 将这些新创建
我使用 OpenXML SDK 2.5 编写了一个 Word 文档,当我在 MS Office 中预览该文档时,该文档给出了预期的外观和格式。 现在我需要将此文档转换为 HTML 文档,我开始了解 O
我是 .net 编码员,我对 ColdFusion 真的很陌生。我编写了一个自动生成发票的 .dll 库。我需要使用 ColdFusion 应用程序中的库。我已经成功地将我的库中的类加载为 coldf
以前我发布了一个问题,如何将数据集中的数据填充到 excel 工作表中,而不是如何使用该数据创建图表。那篇文章不太走运,但现在我设法从数据集中填充数据,但也在努力根据该数据创建图表,我希望图表与我的数
快要被这个问题搞疯了。我确信它是如此简单,我只是错过了它,但我一生都无法找出如何使用 C# 中的 OpenXml SDK v2.0 更改 Word 2007 中的内容控件的内容。 我创建了一个带有纯文
我正在编写一个小应用程序,它将路径作为输入,然后获取该路径中的每个 docx 文件,用关键字替换每个超链接。 奇怪的是,我发现了两种超链接,第一种来自 WordprocessingDocument E
我有一段文字想在文档的中央出现。如何在docx4j中执行此操作?我目前正在使用: PPr paragraphProperties = factory.createPPr(); //cr
我是一名优秀的程序员,十分优秀!