【问题标题】:Delete an element if any level of Children or Children's children doesn't have a praticular value如果任何级别的子级或子级的子级没有实用值,则删除一个元素
【发布时间】:2020-02-28 19:36:40
【问题描述】:

我在 SQL Server 表中有一个 XML 列。我想删除某些元素并从该 XML 列中提取其余信息。

CREATE TABLE #TempTable (xmlDoc xml)

INSERT INTO #TempTable (xmlDoc)
SELECT TOP 1 ai.[XMLDocument].value('(/RequestInfo/TransDocument)[1]','varchar(max)') AS xmlDoc FROM [dbo].[FormDetails] WHERE  [FormID] = xyz 

如果任何级别的子级(或子级的子级)没有特定值,我想删除所有这些元素。 在下面给出的示例中,我想删除所有 <FormDetail> 元素,其中 USStateCd 不等于 'NJ'

XML:

<Form>
 <FormDetail>
       <EmployeeInfoGrp>
        <OtherCompletePersonName>
          <PersonFirstNm>LALALALALI</PersonFirstNm>
          <PersonMiddleNm>S</PersonMiddleNm>
          <PersonLastNm>LILILILA</PersonLastNm>
        </OtherCompletePersonName>
        <MailingAddressGrp>
          <USAddressGrp>
            <AddressLine1Txt>108 ABCD AVE</AddressLine1Txt>
            <CityNm>SPRINGFIELD</CityNm>
            ***<USStateCd>TN</USStateCd>***
            <USZIPCd>37100</USZIPCd>
          </USAddressGrp>
        </MailingAddressGrp>
      </EmployeeInfoGrp>
  </FormDetail>

 <FormDetail>
       <EmployeeInfoGrp>
        <OtherCompletePersonName>
          <PersonFirstNm>CHACHACHACHA</PersonFirstNm>
          <PersonMiddleNm>D</PersonMiddleNm>
          <PersonLastNm>CHICHICHI</PersonLastNm>
        </OtherCompletePersonName>
        <MailingAddressGrp>
          <USAddressGrp>
            <AddressLine1Txt> EFGH AVE</AddressLine1Txt>
            <CityNm>bLah</CityNm>
            ***<USStateCd>NJ</USStateCd>***
            <USZIPCd>00111</USZIPCd>
          </USAddressGrp>
        </MailingAddressGrp>
      </EmployeeInfoGrp>
  </FormDetail>
</Form>

【问题讨论】:

    标签: sql-server xml tsql


    【解决方案1】:

    请尝试以下方法。

    SQL

    -- DDL and sample data population, start
    DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, xmldata XML);
    INSERT INTO @tbl (xmldata)
    VALUES
    (N'<Form xmlns="urn:us:go:tr:msg:formtransmitterupstreammessage" xmlns:xsd="w3.org/2001/XMLSchema"
          xmlns:xsi="w3.org/2001/XMLSchema-instance" xmlns:abc="urn:us:gov:treasury:irs:common">
        <FormDetail xmlns="urn:us:go:tr:abc:ext:air" recordType="String" lineNum="0">
            <EmployeeInfoGrp>
                <OtherCompletePersonName>
                    <PersonFirstNm>LALALALALI</PersonFirstNm>
                    <PersonMiddleNm>S</PersonMiddleNm>
                    <PersonLastNm>LILILILA</PersonLastNm>
                </OtherCompletePersonName>
                <MailingAddressGrp>
                    <USAddressGrp>
                        <AddressLine1Txt>108 ABCD AVE</AddressLine1Txt>
                        <CityNm>SPRINGFIELD</CityNm>
                        <USStateCd>TN</USStateCd>
                        <USZIPCd>37100</USZIPCd>
                    </USAddressGrp>
                </MailingAddressGrp>
            </EmployeeInfoGrp>
        </FormDetail>
        <FormDetail xmlns="urn:us:go:tr:abc:ext:air" recordType="String" lineNum="0">
            <EmployeeInfoGrp>
                <OtherCompletePersonName>
                    <PersonFirstNm>CHACHACHACHA</PersonFirstNm>
                    <PersonMiddleNm>D</PersonMiddleNm>
                    <PersonLastNm>CHICHICHI</PersonLastNm>
                </OtherCompletePersonName>
                <MailingAddressGrp>
                    <USAddressGrp>
                        <AddressLine1Txt>EFGH AVE</AddressLine1Txt>
                        <CityNm>bLah</CityNm>
                        <USStateCd>NJ</USStateCd>
                        <USZIPCd>00111</USZIPCd>
                    </USAddressGrp>
                </MailingAddressGrp>
            </EmployeeInfoGrp>
        </FormDetail>
    </Form>');
    -- DDL and sample data population, end
    
    -- before
    SELECT * FROM @tbl;
    
    DECLARE @state CHAR(2) = 'NJ';
    
    ;WITH XMLNAMESPACES (DEFAULT 'urn:us:go:tr:abc:ext:air'
        , 'urn:us:go:tr:msg:formtransmitterupstreammessage' AS ns1)
    UPDATE @tbl
    SET xmldata.modify('delete /ns1:Form/FormDetail[(EmployeeInfoGrp/MailingAddressGrp/USAddressGrp/USStateCd/text())[1] ne sql:variable("@state")]');
    
    -- after
    SELECT * FROM @tbl;
    

    输出

    <Form xmlns="urn:us:go:tr:msg:formtransmitterupstreammessage" xmlns:xsd="w3.org/2001/XMLSchema" xmlns:xsi="w3.org/2001/XMLSchema-instance" xmlns:abc="urn:us:gov:treasury:irs:common">
      <FormDetail xmlns="urn:us:go:tr:abc:ext:air" recordType="String" lineNum="0">
        <EmployeeInfoGrp>
          <OtherCompletePersonName>
            <PersonFirstNm>CHACHACHACHA</PersonFirstNm>
            <PersonMiddleNm>D</PersonMiddleNm>
            <PersonLastNm>CHICHICHI</PersonLastNm>
          </OtherCompletePersonName>
          <MailingAddressGrp>
            <USAddressGrp>
              <AddressLine1Txt>EFGH AVE</AddressLine1Txt>
              <CityNm>bLah</CityNm>
              <USStateCd>NJ</USStateCd>
              <USZIPCd>00111</USZIPCd>
            </USAddressGrp>
          </MailingAddressGrp>
        </EmployeeInfoGrp>
      </FormDetail>
    </Form>
    

    【讨论】:

    • 谢谢@yitzhak,效果很好。我有一个后续问题如何处理具有多个名称空间的 XML。例如:
      w3.org/2001/XMLSchema" xmlns:xsi="w3.org/2001/XMLSchema-instance" xmlns:abc="urn:us:gov:treasury: irs:common"> 由于名称空间,上面的代码没有返回正确的结果.
    • 这就是为什么 DDL 和样本数据群 在提问时如此重要。我更新了答案以适应命名空间。
    • 这样,我这边+1
    猜你喜欢
    • 2021-09-23
    • 1970-01-01
    • 2021-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多