使用FOR XML AUTO控制XML输出

这篇文章描述如何通过使用FORXML AUTO更好的控制XML输出格式。例如添加XML标记。用这个来替代难于理解的FORXML EXPLICIT语句。如果你在应用程序中即将反序列化输出的XML,你就会觉得这个信息对你有用。

在For XML从句中,您通常使用下列方式之一:

RAW

AUTO

EXPLICIT

PATH

如果你想完全掌控产生的XML,可以使用FORXML EXPLICIT。但是它理解起来相当的困难,后面还要维护复杂的select语句。FORXML AUTO能产生最可读的SELECT语句,但是它也有缺点,不容易控制生成的XML。但使用一些技巧,例如通过使用额外的PATH选项,你可以做一些超过你预期的事情。RAW选项是很少使用,因此不讨论。PATH选项允许您很容易地混合属性和元素。现在,让我们来使用FORXML AUTO

在这个例子中,我们使用的是1:N关系的两个简单的数据表。一个表(SalesOrder)包含客户信息的订单,例外一张表(Items)中包含的具体的项。一个订单可以有多个项,一个项往往只属于一个订单。

以最容易的开始。

SELECT * FROM salesorder

产生:

ordernumbercustomernamecustomerstreet
-- -----------------------------------
1 parkerfirstav
2 lesleysecav

如果你想要使结果集是XML,我们添加FORXML AUTO语句:

SELECT * FROM salesorder FOR XMLAUTO

它产生:

< salesorder ordernumber ="1" customername ="parker" customerstreet ="firstav" />
< salesorder ordernumber ="2" customername ="lesley" customerstreet ="secav" />

现在,字段是作属性的,大多数情况下希望他们是元素。为了做到这点,添加ELEMENTS参数

SELECT * FROM salesorder FOR XMLAUTO,ELEMENTS

它产生:

< salesorder >
< ordernumber > 1 </ ordernumber >
< customername > parker </ customername >
</ salesorder >

如果你想要更改'salesorder' 标签,使用:

SELECT * FROM salesorder AS niceorder FOR XMLAUTO,ELEMENTS

它产生:

< niceorder >
< ordernumber > 1 </ ordernumber >
< customername > parker </ customername >
</ niceorder >

当然,这一招也适用的列名:

SELECT ordernumber AS order_no FROM salesorder WHERE ordernumber = 1 FOR XMLAUTO,ELEMENTS

它产生:

< salesorder >
< order_no > 1 </ order_no >
</ salesorder >

如果你想添加其他标签或节点?例如,对有关客户信息添加'customer''标记?但对FOR XML AUTO来说,被证明是很困难的事件。一个可能的解决方案是使用SELF JOIN(join相同的表),但我找到一个更容易办法。经过一番摆弄和修订,我们使用子查询和有点滥用FOR XML PATH命令。

代码
SELECT
ordernumber,
(
SELECT customername,
customerstreet
FOR XMLPATH( '' ),
TYPE,ELEMENTS)
as customer
FROM
salesorder
FOR XMLAUTO,ELEMENTS

它产生:

代码
< salesorder >
< ordernumber > 1 </ ordernumber >
< customer >
< customername > parker </ customername >
< customerstreet > firstav </ customerstreet >
</ customer >
</ salesorder >
< salesorder >
< ordernumber > 2 </ ordernumber >
< customer >
< customername > lesley </ customername >
< customerstreet > secav </ customerstreet >
</ customer >
</ salesorder >

注意使用附加的'TYPE’参数。这将确保子查询的结果将返回的是一个XML类型(作为整个XML类型的结果的一部分),而不是NVARCHAR(MAX)类型。如果您要对整个结果添加外围标签,也是简单的小把戏:

SELECT (
SELECT
customername
FROM
salesorder
FOR XMLAUTO,TYPE,ELEMENTS
)
AS orderrequest FOR XMLPATH( '' ),ELEMENTS

它产生:

< orderrequest >
< salesorder >
< customername > parker </ customername >
</ salesorder >
< salesorder >
< customername > lesley </ customername >
</ salesorder >
</ orderrequest >

为什么我们在子查询中不使用FOR XML AUTO?试试,它会产生一个错误。当子查询是查询一个实际的表时,您才能使用FOR XML AUTO(上述显然不是)。

如果您想对所生产的XML完全控制,子查询是条出路。比方说,我们希望,每个订单,客户的名字和所有的项都属于订单。为此,您使用这样的相关子查询:

SELECT
customername,
(
SELECT * FROM item WHERE item.ordernumber =
salesorder.ordernumber
FOR XMLAUTO,ELEMENTS)
FROM
salesorder
FOR XMLAUTO,ELEMENTS

它产生:

代码
< salesorder >
< customername > parker </ customername >
< item >
< itemnumber > 10 </ itemnumber >
< description > pen </ description >
< ordernumber > 1 </ ordernumber >
</ item >
< item >
< itemnumber > 11 </ itemnumber >
< description > paper </ description >
< ordernumber > 1 </ ordernumber >
</ item >
</ salesorder >

当使用关联子查询,你可以使用规则的FOR XML AUTO,ELEMENTS语句。如果你想要在'items'外围有一个标签,只需在子查询后添加as,例如:

  • 代码
    SELECT
    customername,
    (
    SELECT * FROM item WHERE item.ordernumber =
    salesorder.ordernumber
    FOR XMLAUTO,ELEMENTS)
    AS orderitems
    FROM
    salesorder
    FOR XMLAUTO,ELEMENTS

    它产生:

    代码
    < salesorder >
    < customername > parker </ customername >
    < orderitems >
    < item >
    < itemnumber > 10 </ itemnumber >
    < description > pen </ description >
    < ordernumber > 1 </ ordernumber >
    </ item >
    < item >
    < itemnumber > 11 </ itemnumber >
    < description > paper </ description >
    < ordernumber > 1 </ ordernumber >
    </ item >
    </ orderitems >
    </ salesorder >

    为什么我们不只是简单的连接item表和order表。这有时会导致不必要的和不可预测的情况,涉及到产生XML布局:

  • 例如:

  • SELECT
    item.description,
    salesorder.customername
    FROM
    salesorder
    INNER JOIN item ON item.ordernumber = salesorder.ordernumber
    FOR XMLAUTO,ELEMENTS

    会产生这样的垃圾:

    代码
    < item >
    < description > pen </ description >
    < salesorder >
    < customername > parker </ customername >
    </ salesorder >
    </ item >
    < item >
    < description > paper </ description >
    < salesorder >
    < customername > parker </ customername >
    </ salesorder >
    </ item >
  • 此外,如果使用连接查询,你很难添加一个外围的标签。因此,对于大多数的控制,使用FORXML AUTO和关联子查询。

  • 版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

    相关推荐


    php输出xml格式字符串
    J2ME Mobile 3D入门教程系列文章之一
    XML轻松学习手册
    XML入门的常见问题(一)
    XML入门的常见问题(三)
    XML轻松学习手册(2)XML概念
    xml文件介绍及使用
    xml编程(一)-xml语法
    XML文件结构和基本语法
    第2章 包装类
    XML入门的常见问题(二)
    Java对象的强、软、弱和虚引用
    JS解析XML文件和XML字符串详解
    java中枚举的详细使用介绍
    了解Xml格式
    XML入门的常见问题(四)
    深入SQLite多线程的使用总结详解
    PlayFramework完整实现一个APP(一)
    XML和YAML的使用方法
    XML轻松学习总节篇