xml - TSQL XML 将节点值转换为 int

标签 xml tsql xpath xquery xml-dml

我在 TSQL 中有 XML,

Declare @xml XML = '<soap:Envelope xmlns:q1="urn:customization_2015_2.setup.webservices.netsuite.com" xmlns:urn1="urn:core_2015_2.platform.webservices.netsuite.com" xmlns:urn="urn:messages_2015_2.platform.webservices.netsuite.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body xmlns:q1="urn:customization_2015_2.setup.webservices.netsuite.com" xmlns:urn1="urn:core_2015_2.platform.webservices.netsuite.com" xmlns:urn="urn:messages_2015_2.platform.webservices.netsuite.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
        <upsertList>
            <q1:record xmlns:q1="urn:customization_2015_2.setup.webservices.netsuite.com"  xsi:type="q1:CustomRecord" externalId="F95C35CF-950E-4756-8C33-43CA0C47FF45">
                <q1:recType internalId="12" type="customRecord"/>
                <q1:customFieldList xmlns="urn:core_2015_2.platform.webservices.netsuite.com">
                    <customField scriptId="custrecord_sps_content_package" xsi:type="SelectCustomFieldRef">
                        <value internalId="25"/>
                    </customField>
                    <customField scriptId="custrecord_sps_content_item" xsi:type="SelectCustomFieldRef">
                        <value internalId="1849"/>
                    </customField>
                    <customField scriptId="custrecord_sps_content_qty" xsi:type="LongCustomFieldRef">
                        <value>6.00</value>
                    </customField>
                </q1:customFieldList>
            </q1:record>
            <q1:record  xmlns:q1="urn:customization_2015_2.setup.webservices.netsuite.com"  externalId="D596F4DB-D7FE-409A-9D40-916FF88FB188">
                <q1:recType internalId="12" type="customRecord"/>
                <q1:customFieldList xmlns="urn:core_2015_2.platform.webservices.netsuite.com">
                    <customField scriptId="custrecord_sps_content_package" xsi:type="SelectCustomFieldRef">
                        <value internalId="24"/>
                    </customField>
                    <customField scriptId="custrecord_sps_content_item" xsi:type="SelectCustomFieldRef">
                        <value internalId="1902"/>
                    </customField>
                    <customField scriptId="custrecord_sps_content_qty" xsi:type="LongCustomFieldRef">
                        <value>2.00</value>
                    </customField>
                </q1:customFieldList>
            </q1:record>
        </upsertList>
    </soap:Body>
</soap:Envelope>'

现在,我想找到 customField 具有属性 => xsi:type="LongCustomFieldRef"然后将值更新为整数。
意思是我想要 Integer: 6 而不是 6.00
<customField scriptId="custrecord_sps_content_qty" xsi:type="LongCustomFieldRef">
                        <value>6</value>
                    </customField>

最佳答案

我不知道,为什么你需要这个。带有 .00 的数字将被强制转换为 int 没有任何麻烦。如果这主要是装饰性的,我不会碰这个......如果你需要这个(可能是由于非常严格的模式检查),你可以走这条路,但这不是微不足道的:

您可能知道,XML 的 .modify()每次调用只能更新一个值。这是相当有限的。

如果您的结构始终相同,则可以使用 CTE将其分解成碎片并从头开始重新构建 XML。但这可能会给您的命名空间带来新的麻烦。

你可以试试这个:

--你的 XML

DECLARE @xml XML = '<soap:Envelope xmlns:q1="urn:customization_2015_2.setup.webservices.netsuite.com" 
                                   xmlns:urn1="urn:core_2015_2.platform.webservices.netsuite.com" 
                                   xmlns:urn="urn:messages_2015_2.platform.webservices.netsuite.com" 
                                   xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                                   xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body xmlns:q1="urn:customization_2015_2.setup.webservices.netsuite.com" xmlns:urn1="urn:core_2015_2.platform.webservices.netsuite.com" xmlns:urn="urn:messages_2015_2.platform.webservices.netsuite.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
        <upsertList>
            <q1:record xmlns:q1="urn:customization_2015_2.setup.webservices.netsuite.com"  xsi:type="q1:CustomRecord" externalId="F95C35CF-950E-4756-8C33-43CA0C47FF45">
                <q1:recType internalId="12" type="customRecord"/>
                <q1:customFieldList xmlns="urn:core_2015_2.platform.webservices.netsuite.com">
                    <customField scriptId="custrecord_sps_content_package" xsi:type="SelectCustomFieldRef">
                        <value internalId="25"/>
                    </customField>
                    <customField scriptId="custrecord_sps_content_item" xsi:type="SelectCustomFieldRef">
                        <value internalId="1849"/>
                    </customField>
                    <customField scriptId="custrecord_sps_content_qty" xsi:type="LongCustomFieldRef">
                        <value>6.00</value>
                    </customField>
                </q1:customFieldList>
            </q1:record>
            <q1:record  xmlns:q1="urn:customization_2015_2.setup.webservices.netsuite.com"  externalId="D596F4DB-D7FE-409A-9D40-916FF88FB188">
                <q1:recType internalId="12" type="customRecord"/>
                <q1:customFieldList xmlns="urn:core_2015_2.platform.webservices.netsuite.com">
                    <customField scriptId="custrecord_sps_content_package" xsi:type="SelectCustomFieldRef">
                        <value internalId="24"/>
                    </customField>
                    <customField scriptId="custrecord_sps_content_item" xsi:type="SelectCustomFieldRef">
                        <value internalId="1902"/>
                    </customField>
                    <customField scriptId="custrecord_sps_content_qty" xsi:type="LongCustomFieldRef">
                        <value>2.00</value>
                    </customField>
                </q1:customFieldList>
            </q1:record>
        </upsertList>
    </soap:Body>
</soap:Envelope>';

--写入临时表
SELECT @xml AS TheXml INTO #tmpXml;

--读取给定xsi:type的所有值其中值包含 dot-- 关注:您的 customFieldList定义了一个新的 默认 命名空间!

WITH XMLNAMESPACES('http://schemas.xmlsoap.org/soap/envelope/' AS [soap]
                  ,'urn:customization_2015_2.setup.webservices.netsuite.com' AS q1
                  ,'http://www.w3.org/2001/XMLSchema-instance' as xsi
                  ,'urn:core_2015_2.platform.webservices.netsuite.com' AS innerDflt)
SELECT r.value('@externalId','uniqueidentifier') AS Record_ExternalId
      ,cf.value('@scriptId','nvarchar(max)') AS CustomField_ScriptId
      ,cf.value('(innerDflt:value/text())[1]','decimal(10,4)') AS OriginalValue
      ,CAST(cf.value('(innerDflt:value/text())[1]','decimal(10,4)') AS INT) AS CastedValue
INTO #tmpValues
FROM #tmpXml
CROSS APPLY TheXml.nodes('/soap:Envelope
                          /soap:Body
                          /upsertList
                          /q1:record') AS A(r)
CROSS APPLY A.r.nodes('q1:customFieldList
                      /innerDflt:customField[@xsi:type="LongCustomFieldRef" and innerDflt:value[contains(text()[1],".")]]') AS B(cf);

--中间结果
SELECT * FROM #tmpXml 
SELECT * FROM #tmpValues;

--使用CURSOR阅读这些行和.modify()替换“错误”的值。

DECLARE @rId NVARCHAR(MAX), @fId NVARCHAR(MAX), @v NVARCHAR(MAX);

DECLARE cur CURSOR FOR SELECT Record_ExternalId
                             ,CustomField_ScriptId
                             ,CAST(CastedValue AS NVARCHAR(MAX)) 
                       FROM #tmpValues;
OPEN cur;
FETCH NEXT FROM cur INTO @rId,@fId,@v;
WHILE @@FETCH_STATUS=0
BEGIN
    WITH XMLNAMESPACES(  'http://schemas.xmlsoap.org/soap/envelope/' AS [soap]
                        ,'urn:customization_2015_2.setup.webservices.netsuite.com' AS q1
                        ,'http://www.w3.org/2001/XMLSchema-instance' as xsi
                        ,'urn:core_2015_2.platform.webservices.netsuite.com' AS innerDflt)
    UPDATE #tmpXml SET TheXml.modify('replace value of (/soap:Envelope
                                                        /soap:Body
                                                        /upsertList
                                                        /q1:record[@externalId=sql:variable("@rId")]
                                                        /q1:customFieldList
                                                        /innerDflt:customField[@scriptId=sql:variable("@fId")]
                                                        /innerDflt:value
                                                        /text())[1] with sql:variable("@v")');

    FETCH NEXT FROM cur INTO @rId,@fId,@v;
END
CLOSE cur;
DEALLOCATE cur;

--重置@xml
SET @xml=(SELECT TheXml FROM #tmpXml);

- 最后结果
SELECT @xml;

关于xml - TSQL XML 将节点值转换为 int,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49730402/

相关文章:

c# - 努力估计 : using C/Win32 or learning C#/. NET

sql - 如何从 SQL Server 数据库中删除所有外键?

sql - 如果记录已存在,则停止在表中插入

sql-server - Transact-SQL 中分隔标识符是否被视为 "best-practice"?

java - 如何在不从其后代检索文本的情况下获取元素的文本

xpath - 如何在html head中使用xpath脚本进行选择?

c# - Log4Net 在单独的配置文件中

java - JAXB 与 Axis2 在序列化时放置对象 ID

Java JAXB : XML to Java object conversion

xml - 迭代不起作用,只返回一个项目