最簡單的XML用法

来源:http://www.cnblogs.com/ljhdo/archive/2017/07/06/5176563.html
-Advertisement-
Play Games

在傳遞數據時,XML和JSON是最常用的數據格式,SQL Server從很早的版本就開始支持XML格式,而對於JSON格式,SQL Server從2016版本開始支持。大多數資料庫系統並沒有升級到SQL Server 2016版本,因此在傳遞格式化的數據時,通常還是使用XML格式。對我而言,查詢和解 ...


在傳遞數據時,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)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 以下信息由何問起收集,希望有幫助。 可根據下表中給出的信息確定最能滿足需要的功能集合。 轉自:http://hovertree.com/h/bjag/ir3sc4mp.htm 推薦:http://www.cnblogs.com/sosoft/category/413157.html ...
  • 全部表 select table_name from user_tables; //當前用戶擁有的表 select table_name from all_tables; //所有用戶的表 select table_name from dba_tables; //包括系統表 表的註釋 select ... ...
  • 很久之前用到的,現在整理在這,裡面一些代碼來源於網上,不過有些bug已被我修改了。 1.查詢結果轉XML 其中 為要查詢的語句, XML格式數據, XML轉成字元串 2.查詢結果轉JSON 查詢結果轉換成json需要經過兩個步驟,首先將查詢結果轉成XML數據,然後通過XML數據轉成json XML轉 ...
  • 右擊還存在的訂閱,生成腳本,有個過程sp_addpullsubscription_agent 執行,發現報錯說distribution agent 已經存在 執行: UPDATE dbo.MSreplication_subscriptions SET distribution_agent =NULL ...
  • GETDATE,datepart,DATEPART,DATEADD,DATEDIFF,DATENAME,YEAR,MONTH,DAY,CONVERT ...
  • 通過存儲過程獲取當前日期(或指定日期)所在的日期區間,包含年、月、周、日。 sql CREATE PROCEDURE [dbo].[GetDataPeriod] @defaultDate DATE=NULL, @period VARCHAR(1)=NULL, @startDate DATE OUTP ...
  • 一、確認防火牆沒有阻止3306埠(一般伺服器預設會屏蔽掉) windows防火牆例外設置方法 控制面板(右上角選擇查看方式為大圖標) 防火牆 高級設置 高級設置 出站規則 最右邊 新建規則“新建出站規則嚮導”,在嚮導的第一步,選擇要創建的防火牆規則類型,選擇第二個“埠”。 windows防火牆添 ...
  • jdbc.driverClassName=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/database?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewr ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...