【问题标题】:TSQL XML Convert node value to intTSQL XML 将节点值转换为 int
【发布时间】:2018-04-09 10:06:38
【问题描述】:

我在 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" 然后将 Value 更新为 Integer。 意思是我想要 Integer: 6 而不是 6.00

<customField scriptId="custrecord_sps_content_qty" xsi:type="LongCustomFieldRef">
                        <value>6</value>
                    </customField>

【问题讨论】:

    标签: xml tsql xpath xquery xml-dml


    【解决方案1】:

    我不知道,你为什么需要这个。带有.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定义了一个新的default命名空间!

    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;
    

    【讨论】:

    • 谢谢Shnugo。问题原因是,在DB中构建XML的数量是十进制(18,2),但是,服务器不接受.00,它必须是整数。
    • @CristenRafalko 用CAST SomeDecValue AS INT 构造 XML 不是更容易吗?
    猜你喜欢
    • 2014-07-16
    • 1970-01-01
    • 2021-11-14
    • 1970-01-01
    • 2011-01-07
    • 2014-11-21
    • 2013-06-16
    • 1970-01-01
    • 2018-10-26
    相关资源
    最近更新 更多