这与SQL Data as XML Element 非常相似——以至于我认为它可能是重复的——但我想根据您的上下文进一步解释一下为什么这不是最好的主意。在我对这个问题的回答中,我展示了一种非常老套的方法,你可以这样做,但这不是最好的主意。
几乎不可能为您的 XML 创建架构。该 XML 的任何使用者将永远无法确定哪些值可能作为元素出现。与其尝试创建动态元素,不如使用某种属性。您甚至可以使用xsi:type 在您的各种XML 中创建一个抽象类型(尽管在我的示例中我只是使用一个普通的旧属性——您可以选择对您的消费者最有意义的任何属性)。该 XML 的查询将是:
declare @subjects TABLE(studentno int, name varchar(10), subjecT varchar(10), mark int, grade char(1))
INSERT @subjects
VALUES
(1, 'John','English', 41,'A'),
(1, 'John','Hindi', 42,'B')
select
s.Name
,(SELECT
s2.Subject as '@type'
,s2.Mark
,s2.Grade
FROM @subjects s2
WHERE s2.studentno = s.studentno
FOR XML PATH('Subject'), ROOT('Subjects'), TYPE)
from @subjects s
GROUP BY s.name, s.studentno
FOR XML PATH('Student')
产生:
<Student>
<Name>John</Name>
<Subjects>
<Subject type="English">
<Mark>41</Mark>
<Grade>A</Grade>
</Subject>
<Subject type="Hindi">
<Mark>42</Mark>
<Grade>B</Grade>
</Subject>
</Subjects>
</Student>
消费者可以理解此 XML,例如,他们可以在不知道可能存在哪些主题的情况下迭代主题(并且无需假设Subjects 的每个直接子代都在实际上是一个主题,而不是在新版本的架构中添加的其他类型的节点)。
如果您真的需要该输出,我更愿意使用 XSLT 将上面的输出转换为您的格式,例如:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="Subject">
<xsl:element name="{@type}">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="Subjects">
<xsl:element name="Subject">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
</xsl:transform>
得到你
<?xml version="1.0" encoding="UTF-8"?>
<Student>
<Name>John</Name>
<Subject>
<English>
<Mark>41</Mark>
<Grade>A</Grade>
</English>
<Hindi>
<Mark>42</Mark>
<Grade>B</Grade>
</Hindi>
</Subject>
</Student>
请注意,您不能完全使用 SQL Server 做到这一点 - 您必须求助于构建 XML 字符串并将其转换为 XML,就像在我的其他答案中一样。