如何更改xml中所有日期的格式?

时间:2017-08-13 08:29:02

标签: sql sql-server regex xml tsql

我在SQL的单元格中有一个xml,如:

表:

table

    <?xml version="1.0" encoding="utf-16"?>
    <Document xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <Page W="2480" H="3516">
            <Word L="1871" R="2031" T="221" B="252" Text="INVOICE" Id="25509747671106" />
            <Word L="1988" R="2046" T="2232" B="2279" Text="tf.'l" Id="25886807122412" />
            <Word L="1872" R="1990" T="324" B="351" Text="26603333345"Id="24493329746300" />
            <Word L="1871" R="2015" T="373" B="401" Text="08-02-17" Id="25109308586898" />
            <Word L="1873" R="2007" T="422" B="448" Text="S-44404" Id="24914704754685" />
            <Word L="1874" R="1887" T="468" B="496" Text="1" Id="22024234663427" />
            <Word L="1068" R="1148" T="1278" B="1309" Text="DHL" Id="8152496756181" />
            <Word L="1692" R="1848" T="1279" B="1310" Text="08-02-17" Id="21119731019927" />
            <Word L="2096" R="2251" T="1278" B="1310" Text="10-01-17" Id="31333127836454" />
            <Word L="112" R="243" T="1352" B="1358" Text="_" Id="365589546232" />
            <Word L="252" R="411" T="1322" B="1350" Text="QUANTITY" Id="1050334834310" />
            <Word L="1415" R="1913" T="745" B="787" Text="______ShlpTo" Id="22635743273663" />
     </Page>
   </Document>

我需要更新[FRData]并将格式从 mm-dd-yy 更改为格式 yyyy-mm-dd 在所有xml中。

我写了一个正则表达式来验证所寻求的日期格式:

^(0?[1-9]|1[012])[\-](0?[1-9]|[12][0-9]|3[01])[\-]\d{2}$

我知道如何将日期格式 mm-dd-yy 更改为 yyyy-mm-dd

select left(convert(varchar, cast('08-02-17' as datetime), 120),10)

但我不知道如何更改整个xml中的日期

4 个答案:

答案 0 :(得分:0)

试试xml linq

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            StreamReader reader = new StreamReader(FILENAME,Encoding.Unicode);
            reader.ReadLine();
            XDocument doc = XDocument.Load(reader);

            foreach (XElement word in doc.Descendants("Word"))
            {
                DateTime date;
                Boolean isDate = DateTime.TryParse((string)word.Attribute("Text"), out date);
                if (isDate)
                {
                    word.Attribute("Text").SetValue(date.ToString("yyyy-MM-dd"));
                }

            }

        }
    }
}

答案 1 :(得分:0)

Try this please.

declare @I int
declare @X nvarchar(100)
declare @D date

select @I = max(FRData.value('count(/Document/Page//Word)', 'int'))
from #t

while @I > 0
begin

    set @X = (select top 1 FRData.value('(/Document/Page//Word/@Text)[sql:variable("@I")][1]', 'nvarchar(100)')
              from #t)

    if isdate(@X) = 1
    begin
        set @D = convert(date, @X)

        update #t
        set FRData.modify('replace value of ((/Document/Page//Word/@Text)[sql:variable("@I")])[1]
                           with sql:variable("@D")')
    end

    set @I = @I - 1
end

答案 2 :(得分:0)

您可能正在寻找: SET DATEFORMAT

SET DATEFORMAT ymd;

文档:https://docs.microsoft.com/en-us/sql/t-sql/statements/set-dateformat-transact-sql

但是这将取决于您创建xml的脚本,因为可能需要转换/转换您的日期格式。

答案 3 :(得分:0)

你正在处理一个非常糟糕的XML:

  • 您应该将XML存储在本机类型的XML列中。前导<?xml version="1.0" encoding="utf-16">清楚地表明,您将其存储为某种字符串。 XML不会存储为您看到的文本,而是存储为层次结构树。这使得XML速度惊人。您的方法必须一遍又一遍地解析XML ...
  • 您绝不应使用文化相关日期/时间格式
  • 更糟糕的是:永远不要使用2字节年份的日期格式(01-02-03将被视为完全不同的值,具体取决于系统的设置!)
  • Xml无效:Text="26603333345"Id="24493329746300"Id
  • 之前缺少空白

你自己的做法很危险:

  

我知道如何将日期格式mm-dd-yy更改为yyyy-mm-dd:   select left(convert(varchar, cast('08-02-17' as datetime), 120),10)

第一步是cast('08-02-17' as datetime)。这将隐含地依赖于您的系统设置

最好尝试select left(convert(varchar, CONVERT(DATETIME,'08-02-17',1), 120),10)

接受的答案使用if isdate(@X) = 1,由于同样的原因,这是危险的。

但是你想要实现的是好的yyyy-m-dd是ISO8601,应该是XML中的日期格式:

您可以使用XQuery with FLWOR

DECLARE @dummy TABLE(ID INT IDENTITY,YourXML NVARCHAR(MAX));
INSERT INTO @dummy VALUES
(N'<Document xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <Page W="2480" H="3516">
            <Word L="1871" R="2031" T="221" B="252" Text="INVOICE" Id="25509747671106" />
            <Word L="1988" R="2046" T="2232" B="2279" Text="tf.''l" Id="25886807122412" />
            <Word L="1872" R="1990" T="324" B="351" Text="26603333345" Id="24493329746300" />
            <Word L="1871" R="2015" T="373" B="401" Text="08-02-17" Id="25109308586898" />
            <Word L="1873" R="2007" T="422" B="448" Text="S-44404" Id="24914704754685" />
            <Word L="1874" R="1887" T="468" B="496" Text="1" Id="22024234663427" />
            <Word L="1068" R="1148" T="1278" B="1309" Text="DHL" Id="8152496756181" />
            <Word L="1692" R="1848" T="1279" B="1310" Text="08-02-17" Id="21119731019927" />
            <Word L="2096" R="2251" T="1278" B="1310" Text="10-01-17" Id="31333127836454" />
            <Word L="112" R="243" T="1352" B="1358" Text="_" Id="365589546232" />
            <Word L="252" R="411" T="1322" B="1350" Text="QUANTITY" Id="1050334834310" />
            <Word L="1415" R="1913" T="745" B="787" Text="______ShlpTo" Id="22635743273663" />
     </Page>
   </Document>');

WITH CastedToXML AS
(
    SELECT ID 
          ,CAST(YourXML AS XML) AS TheXml
    FROM @dummy
)
SELECT ID 
      ,TheXml.query
      (N'
        <Document><Page>
        {
            for $w in /Document/Page/Word
            return 
            if(string-length($w/@Text)=8 and substring($w/@Text,3,1)="-" and substring($w/@Text,6,1)="-") 
            then
                <Word L="{$w/@L}" R="{$w/@R}" T="{$w/@T}" B="{$w/@B}" Text="{concat("20",substring($w/@Text,7,2),"-",substring($w/@Text,1,5))}" Id="{$w/@Id}" />
            else
                $w
        }
        </Page></Document>
      ')
FROM CastedToXML;

结果:

<Document>
  <Page>
    <Word L="1871" R="2031" T="221" B="252" Text="INVOICE" Id="25509747671106" />
    <Word L="1988" R="2046" T="2232" B="2279" Text="tf.'l" Id="25886807122412" />
    <Word L="1872" R="1990" T="324" B="351" Text="26603333345" Id="24493329746300" />
    <Word L="1871" R="2015" T="373" B="401" Text="2017-08-02" Id="25109308586898" />
    <Word L="1873" R="2007" T="422" B="448" Text="S-44404" Id="24914704754685" />
    <Word L="1874" R="1887" T="468" B="496" Text="1" Id="22024234663427" />
    <Word L="1068" R="1148" T="1278" B="1309" Text="DHL" Id="8152496756181" />
    <Word L="1692" R="1848" T="1279" B="1310" Text="2017-08-02" Id="21119731019927" />
    <Word L="2096" R="2251" T="1278" B="1310" Text="2017-10-01" Id="31333127836454" />
    <Word L="112" R="243" T="1352" B="1358" Text="_" Id="365589546232" />
    <Word L="252" R="411" T="1322" B="1350" Text="QUANTITY" Id="1050334834310" />
    <Word L="1415" R="1913" T="745" B="787" Text="______ShlpTo" Id="22635743273663" />
  </Page>
</Document>

您可以使用相同的方法立即更新可更新的CTE

WITH CastedToXML AS
(
    SELECT ID 
          ,YourXML 
          ,CAST(YourXML AS XML) AS TheXml
    FROM @dummy
)
UPDATE CastedToXML SET YourXml=CAST(TheXml.query
      (N'
        <Document><Page>
        {
            for $w in /Document/Page/Word
            return 
            if(string-length($w/@Text)=8 and substring($w/@Text,3,1)="-" and substring($w/@Text,6,1)="-") 
            then
                <Word L="{$w/@L}" R="{$w/@R}" T="{$w/@T}" B="{$w/@B}" Text="{concat("20",substring($w/@Text,7,2),"-",substring($w/@Text,1,5))}" Id="{$w/@Id}" />
            else
                $w
        }
        </Page></Document>
      ') AS NVARCHAR(MAX));

SELECT * FROM @dummy;

最后建议:将其存储在原生类型的列中!