最简单的XML用法

本文涉及的产品
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云数据库 RDS SQL Server,基础系列 2核4GB
简介:

在传递数据时,XML和JSON是最常用的数据格式,SQL Server从很早的版本就开始支持XML格式,而对于JSON格式,SQL Server从2016版本开始支持。大多数数据库系统并没有升级到SQL Server 2016版本,因此在传递格式化的数据时,通常还是使用XML格式。对我而言,查询和解析XML格式的数据需要掌握的知识点较多,MSDN上关于XML的文档,又试图把XML的各个方面都讲解地清清楚楚,以至于内容冗杂,使学习过程变得困难。我十分不喜欢学习这些不常用的数据结构,再说,在平时的数据库开发中,用到XML的地方也很少,可是,一旦在应用程序中用到XML,就只有头疼的份了,既然避不开XML,那就用最简单的方法学习它,了解它,使用它,以备不时之需。写这篇文章,就是以最简单的方式,分享XML最常用的使用方法。

一,XML数据格式的简单介绍

1,最简单的XML格式

XML数据最简单的格式是:

  • 开始标签:<tag>
  • 标签的属性,属性值用双引号:<tag id="1" name="azure">,在单个节点中,属性名不能重复,属性之间使用空格分隔,在开始标签中,才能设置属性;
  • 结束标签:</tag>,结束标签不能有属性;
  • 子节点:在开始标签和结束标签,可以包含节点,叫做子节点;
  • 节点值:在开始标签和结束标签的标量值,叫做节点值;

2,使用字符串对XML数据赋值

数据类型XML用于存储XML格式化的文本数据,在本例中,声明一个XML类型的变量 @xml,并赋值,后文示例都使用该变量用于数据查询。

复制代码
declare @xml xml
set @xml='
<Expression ID="1" TaxonomyID="1">
  <SubExpression ID="1" OperandType="Tag" Operator="and">
    <Oprand ID="268819" Name="abuse" />
    <Oprand ID="277029" Name="mongohq" />
    <Oprand ID="516813" Name="access" />
  </SubExpression>
  <SubExpression ID="2" OperandType="Tag" Operator="and">
    <Oprand ID="283839" Name="reviews" />
    <Oprand ID="697348" Name="retention" />
  </SubExpression>
  <SubExpression ID="3" OperandType="Tag" Operator="not">
    <Oprand ID="281556" Name="richfaces" />
    <Oprand ID="2993766" Name="rgp" />
  </SubExpression>
</Expression>'
复制代码

二,XPath路径表达式

XPath 使用路径表达式在 XML 文档中选取节点,节点是通过沿着路径选取的,XPath是查询XML数据时必备的参数。

常用的路径表达式是:

  • .   :选取当前节点;
  • ..  :选取当前节点的父节点;
  • /   :从根节点开始;
  • //  :从匹配选择的节点开始选取,而不考虑其位置;
  • *  :通配符,匹配任意字符,或任意节点;
  • node()  :匹配任意节点,跟通配符 * 功能相似; 
  • @PropertyName :选取属性;

在路径表达式中,跟节点的选取有关的表达式是:

  • NodeName:选取指定节点名及其所有子节点;
  • NodeName[N]:选取指定节点集合的第N个节点;
  • NodeName[@Name]:选取当前节点中带有指定属性的节点;

三,XML数据的查询(query()函数

@xml.query(’xpath‘)函数,参数是路径表达式,返回XML数据类型的结果,该XML是非类型化(untyped)的。

1,选取节点及其子节点

示例中,从根节点Expression开始,选取SubExpression节点及其子节点:

select @xml.query('/Expression/SubExpression')

query()函数返回的结果如下,该查询结果是非类型化的XML数据。

复制代码
<SubExpression ID="1" OperandType="Tag" Operator="and">
  <Oprand ID="268819" Name="abuse" />
  <Oprand ID="277029" Name="mongohq" />
  <Oprand ID="516813" Name="access" />
</SubExpression>
<SubExpression ID="2" OperandType="Tag" Operator="and">
  <Oprand ID="283839" Name="reviews" />
  <Oprand ID="697348" Name="retention" />
</SubExpression>
<SubExpression ID="3" OperandType="Tag" Operator="not">
  <Oprand ID="281556" Name="richfaces" />
  <Oprand ID="2993766" Name="rgp" />
</SubExpression>
复制代码

2,选取指定节点的所有子节点集合

select @xml.query('/Expression/SubExpression/node()')
select @xml.query('/Expression/SubExpression/*')

结果集是SubExpression节点下的所有子节点: 

复制代码
<Oprand ID="268819" Name="abuse" />
<Oprand ID="277029" Name="mongohq" />
<Oprand ID="516813" Name="access" />
<Oprand ID="283839" Name="reviews" />
<Oprand ID="697348" Name="retention" />
<Oprand ID="281556" Name="richfaces" />
<Oprand ID="2993766" Name="rgp" />
复制代码

四,XML数据的查询(value()函数)

@xml.value('xpath','sql_data_type'),返回XML数据中单个属性的标量值,在使用value()函数时,xpath 参数必须指定返回的是单个值,而value()函数不会去check返回值的数量。

一般情况下,即使xml数据只有一个属性值,静态类型化(Static typing)要求,xpath表达式也必须显式指定返回单个标量值,因此,必须指定在xpath函数的末尾添加”[1]“,通常的xpath表达式是”(xpath)[1]“。

select @xml.value('(/Expression/SubExpression[1]/@ID)[1]','int')
select @xml.value('(/Expression/SubExpression/@ID)[1]','int')

五,XML数据的查询(nodes()函数) 

@xml.nodes ('xpath') 函数返回节点的集合,用于把XML数据转换为关系数据表,返回的每一个行都是XML数据类型,语法是:

nodes ('xpath') as table(column)  

通过nodes()函数,返回SubExpression节点及其属性,由于单个节点中,属性名不可能重复,因此,在nodes()函数返回的单个节点中,不需要通过xpath路由,直接获取当前节点的属性值,这样,可以在xpath表达式中直接指定属性,不需要显式以“[1]”结尾。

示例代码如下,在value()函数中,直接指定属性值,表示获取当前节点的属性值:

select t.v.query('.') as SubExpression
    ,t.v.value('@ID','int') as SubExpressionID
    ,t.v.value('@OperandType','varchar(16)') as OperandType
    ,t.v.value('@Operator','varchar(16)') as Operator
from @xml.nodes('/Expression/SubExpression') as t(v)

通过cross apply 连接操作,把SubExpression节点下的所有数据都转换为关系型数据,并把该数据存储到临时数据表#Expressions中:

;with cte_Expressions as 
(
    select e.v.query('.') as Expression
        ,e.v.value('@ID','int') as ExpressionID
        ,e.v.value('@TaxonomyID','int') as TaxonomyID
    from @xml.nodes('/Expression') as e(v)
)
,cte_SubExpression as 
(
    select e.ExpressionID
        ,e.TaxonomyID
        ,se.SubExpression
        ,se.SubExpressionID
        ,se.OperandType
        ,se.Operator
    from cte_Expressions e
    cross apply
    (
        select t.v.query('.') as SubExpression
            ,t.v.value('@ID','int') as SubExpressionID
            ,t.v.value('@OperandType','varchar(16)') as OperandType
            ,t.v.value('@Operator','varchar(16)') as Operator
        from e.Expression.nodes('/Expression/SubExpression') as t(v)
    ) as se
)
select p.TaxonomyID
    ,p.ExpressionID
    ,p.SubExpressionID
    ,p.OperandType
    ,p.Operator
    ,d.OperandID
    ,d.OperandName
from cte_SubExpression p
cross apply
(
    select t.v.value('@ID','int') as OperandID
        ,t.v.value('@Name','varchar(32)') as OperandName
    from p.SubExpression.nodes('/SubExpression/Oprand') as t(v)
) as d
View Code

六,把行集数据转化为XML数据(for xml path)

把行集数据转化为XML数据,需要用到for xml path子句,该子句的特点是:

  • path('root') 子句用于指定根节点;
  • select子句的字段别名用于指定属性,别名中必须使用@符号标识出属性名,例如:'@PropertyName';
  • 在select 子句中,如果不在别名中把字段指定为属性,那么该字段的值作为节点值,节点值分为标量类型和XML类型;
    • 对于标量类型,节点值是标量值;
    • 对于XML类型,节点值是子节点的集合;

例如,要把数据转换为如下的关系型数据结构,其SubExpression字段是一个非类型化的XML数据,要完成这样的数据转换,必须使用for xml path子句和cast()类型转换:

复制代码
<SubExpression ID="1" OperandType="Tag" Operator="not">
  <Oprand ID="268819" Name="abuse" />
  <Oprand ID="277029" Name="mongohq" />
  <Oprand ID="516813" Name="access" />
</SubExpression>
<SubExpression ID="2" OperandType="Tag" Operator="not">
  <Oprand ID="283839" Name="reviews" />
  <Oprand ID="697348" Name="retention" />
</SubExpression>
<SubExpression ID="3" OperandType="Tag" Operator="not">
  <Oprand ID="281556" Name="richfaces" />
  <Oprand ID="2993766" Name="rgp" />
</SubExpression>
复制代码

使用类型转换的目的,是为了把for xml path返回的字符串转换成XML数据类型,这样,就能以XML格式嵌入到上次的for xml path的结构中,作为子节点:

;with cte_Expressions as 
(
    select distinct ExpressionID
        ,TaxonomyID
    from #Expressions with(nolock)
) 
,cte_SubExpressions as
(
    select o.ExpressionID
        ,o.SubExpressionID
        ,o.OperandType
        ,o.Operator
    from #Expressions o with(nolock)
    group by o.ExpressionID
        ,o.SubExpressionID
        ,operandType
        ,o.Operator
)
select e.TaxonomyID as TaxonomyID
    ,e.ExpressionID as ExpressionID
    ,cast(
    (
        select o.SubExpressionID as '@ID'
            ,o.OperandType as '@OperandType'
            ,case o.Operator when '&' then 'and' else 'not' end as '@Operator'
            ,cast((
                select op.OperandID as '@ID'
                    ,op.OperandName as '@Name'
                from #Expressions op with(nolock)
                where o.ExpressionID=op.ExpressionID
                    and o.SubExpressionID=op.SubExpressionID
                for xml path('Oprand')            
            )as xml)
        from cte_SubExpressions o
        where o.ExpressionID=e.ExpressionID
        for xml path('SubExpression')
        ) as xml)
        as SubExpressions
from cte_Expressions e
View Code

还有两个函数modify()和exist(),用于XML数据的修改和检查,由于在我当前接触的项目中,没有用到过,我就不写了。

到此,文章也该结尾了,XML的极简用法已经总结了很多,在以后工作中国,如果用到XML时,翻开这篇文章,能够快速解决XML常见的数据查询和解析问题,这样就足够了。

 

参考文档:

Use PATH Mode with FOR XML

XML Data (SQL Server)

作者悦光阴
本文版权归作者和博客园所有,欢迎转载,但未经作者同意,必须保留此段声明,且在文章页面醒目位置显示原文连接,否则保留追究法律责任的权利。
分类: SQL Server
标签: XML

本文转自悦光阴博客园博客,原文链接:http://www.cnblogs.com/ljhdo/p/5176563.html,如需转载请自行联系原作者
相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
7月前
|
XML 存储 JavaScript
XML 简介及用法详解
XML代表eXtensible Markup Language(可扩展标记语言)。XML是一种与HTML非常相似的标记语言。XML被设计用于存储和传输数据。XML被设计成具有自我描述性。XML不执行任何操作,也许有点难理解,但XML不执行任何操作
149 5
|
2月前
|
XML 存储 数据库
xml用法
【10月更文挑战第17天】xml用法
21 7
|
3月前
|
SQL XML Java
mybatis :sqlmapconfig.xml配置 ++++Mapper XML 文件(sql/insert/delete/update/select)(增删改查)用法
当然,这些仅是MyBatis功能的初步介绍。MyBatis还提供了高级特性,如动态SQL、类型处理器、插件等,可以进一步提供对数据库交互的强大支持和灵活性。希望上述内容对您理解MyBatis的基本操作有所帮助。在实际使用中,您可能还需要根据具体的业务要求调整和优化SQL语句和配置。
70 1
|
SQL XML Java
【SQL用法】Mybatis框架中的xml文件中经常使用的sql语句
【SQL用法】Mybatis框架中的xml文件中经常使用的sql语句
138 0
|
XML Android开发 数据格式
Android XML 布局基础(二)ID 用法
Android XML 布局基础(二)ID 用法
345 0
|
XML SQL Java
MyBatis-06 MyBatis XML方式之多个接口参数用法
MyBatis-06 MyBatis XML方式之多个接口参数用法
108 0
|
XML Java 数据库连接
xml语法中<![CDATA[ ]]>的用法
<![CDATA[ ]]> 是什么,这是XML语法。特别是在mybatis中的mapper映射里会经常使用到该模块,具体点来说,当编译时xml文件时,在CDATA内部的所有内容都会被解析器忽略,
1320 0
|
Android开发
Android中string.xml中%1$s、%1$d等的用法
在 TextView 中想要动态的显示某些值,用到%1$s,%1$d,先介绍一下: 感觉有点像正则,But.... dingdang.jpg 还是直接来吧 %n$ms:代表输出的是字符串,n代表是第几个参数,设置m的值可以在输出之前放置空...
1407 0
|
XML SQL 数据格式