SQL парсинг нескольких полей из xml - PullRequest
0 голосов
/ 06 февраля 2020

Мне нужна помощь для извлечения данных xml со связанного сервера и возврата только определенных полей в табличном формате. В идеале я хотел бы заполнить таблицу локального компьютера таблицей A (термин, C, D, F). Вы заметите, что некоторые узлы не имеют C, D или F, поэтому я должен исключить их. Я перепробовал несколько вещей и, похоже, не совсем понял синтаксис. Моя проблема заключается в извлечении данных с удаленного сервера и анализе только нужных мне узлов xml. Небольшая помощь приветствуется.

Running on the remote server:
DECLARE @xml XML
SET @xml = (select top 5 term_uid, field1, term_attributes.query('/') from server.dbo.tableName with (nolock) for xml auto, root('Attributes')
       )
SELECT @xml 

Results:  
<Attributes>
  <server.context.tableName term_uid="7D54155E-75E8-4BBC-9112-0002C70FC781" field1="I71.0">
    <Attributes xmlns="">
      <Attribute name="A">3</Attribute>
      <Attribute name="B">HHS_HCC154</Attribute>
      <Attribute name="C">I71.0</Attribute>
      <Attribute name="D">I71.00</Attribute>
      <Attribute name="F">308546005</Attribute>
    </Attributes>
  </server.context.tablName>
  <server.context.tablName term_uid="1C572AF2-CD26-4C41-B449-0004FF5F4E6E" field1="">
    <Attributes xmlns="">
      <Attribute name="A">2131</Attribute>
      <Attribute name="F">20013001</Attribute>
    </Attributes>
  </server.context.tablName>
  <server.context.tablName term_uid="744A553A-0C2A-4FD7-8004-000519EFAC75" field1="">
    <Attributes xmlns="">
       <Attribute name="D">H66.001</Attribute>
      <Attribute name="F">14948001</Attribute>
    </Attributes>
  </server.context.tablName>
  <server.context.tablName term_uid="5E70C463-4489-4DA7-B410-00082E8E68C5" field1="">
    <Attributes xmlns="">
      <Attribute name="D">S62.353S</Attribute>
      <Attribute name="F">704024008</Attribute>
    </Attributes>
  </server.context.tablName>
  <server.context.tablName term_uid="EEDBCC0B-75B9-47D9-8E7A-000A4B604135" field1="R97.2">
    <Attributes xmlns="">
      <Attribute name="A">3</Attribute>
      <Attribute name="C">R97.2</Attribute>
      <Attribute name="D">790.93</Attribute>
      <Attribute name="F">396152005</Attribute>
    </Attributes>
  </server.context.tablName>
</Attributes>

Also tried doing something like this:
;with listAll as 
    (select term_uid
    ,C= AttributeXML.value('/Attributes/server.context.tableName/Attributes/Attribute/[@name=sql:variable("@C")]/text())[1]','varchar(100')
    ,D= AttributeXML.value('/Attributes/server.context.tableName/Attributes/Attribute/[@name=sql:variable("@D")]/text())[1]','varchar(100') 
    ,F= AttributeXML.value('/Attributes/server.context.tableName/Attributes/Attribute/[@name=sql:variable("@F")]/text())[1]','varchar(100')  
        from server.context.tableName 
        cross apply
            AttributeXML.nodes('/Attributes/server.context.tableName/Attributes/Attribute') as XTbl(XProp)
)
select * from listAll

Ответы [ 2 ]

1 голос
/ 06 февраля 2020

Проверьте это. Выражение предиката XPath проверяет наличие всех трех обязательных атрибутов: C, D и F.

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (term_uid VARCHAR(50) PRIMARY KEY, xmldata XML);
INSERT INTO @tbl (term_uid, xmldata)
VALUES
('7D54155E-75E8-4BBC-9112-0002C70FC781',
N'<Attributes>
    <server.context.tablName term_uid="7D54155E-75E8-4BBC-9112-0002C70FC781" field1="I71.0">
        <Attributes xmlns="">
            <Attribute name="A">3</Attribute>
            <Attribute name="B">HHS_HCC154</Attribute>
            <Attribute name="C">I71.0</Attribute>
            <Attribute name="D">I71.00</Attribute>
            <Attribute name="F">308546005</Attribute>
        </Attributes>
    </server.context.tablName>
    <server.context.tablName term_uid="1C572AF2-CD26-4C41-B449-0004FF5F4E6E" field1="">
        <Attributes xmlns="">
            <Attribute name="A">2131</Attribute>
            <Attribute name="F">20013001</Attribute>
        </Attributes>
    </server.context.tablName>
    <server.context.tablName term_uid="744A553A-0C2A-4FD7-8004-000519EFAC75" field1="">
        <Attributes xmlns="">
            <Attribute name="D">H66.001</Attribute>
            <Attribute name="F">14948001</Attribute>
        </Attributes>
    </server.context.tablName>
    <server.context.tablName term_uid="5E70C463-4489-4DA7-B410-00082E8E68C5" field1="">
        <Attributes xmlns="">
            <Attribute name="D">S62.353S</Attribute>
            <Attribute name="F">704024008</Attribute>
        </Attributes>
    </server.context.tablName>
    <server.context.tablName term_uid="EEDBCC0B-75B9-47D9-8E7A-000A4B604135" field1="R97.2">
        <Attributes xmlns="">
            <Attribute name="A">3</Attribute>
            <Attribute name="C">R97.2</Attribute>
            <Attribute name="D">790.93</Attribute>
            <Attribute name="F">396152005</Attribute>
        </Attributes>
    </server.context.tablName>
</Attributes>');
-- DDL and sample data population, end

SELECT term_uid
    , p.value('@term_uid','VARCHAR(50)') AS term
    , c.value('(Attribute[@name="C"]/text())[1]','VARCHAR(10)') AS c
    , c.value('(Attribute[@name="D"]/text())[1]','VARCHAR(10)') AS d
    , c.value('(Attribute[@name="F"]/text())[1]','VARCHAR(10)') AS f
FROM @tbl AS tbl
    CROSS APPLY tbl.xmldata.nodes('/Attributes/server.context.tablName') AS parent(p)
    CROSS APPLY p.nodes('Attributes[Attribute[@name="C"] 
        and Attribute[@name="D"] 
        and Attribute[@name="F"]]') AS child(c);

Вывод

+--------------------------------------+--------------------------------------+-------+--------+-----------+
|               term_uid               |                 term                 |   c   |   d    |     f     |
+--------------------------------------+--------------------------------------+-------+--------+-----------+
| 7D54155E-75E8-4BBC-9112-0002C70FC781 | 7D54155E-75E8-4BBC-9112-0002C70FC781 | I71.0 | I71.00 | 308546005 |
| 7D54155E-75E8-4BBC-9112-0002C70FC781 | EEDBCC0B-75B9-47D9-8E7A-000A4B604135 | R97.2 | 790.93 | 396152005 |
+--------------------------------------+--------------------------------------+-------+--------+-----------+
0 голосов
/ 07 февраля 2020

Это сработало для меня, но я бы не оказался там без тебя. Спасибо!

insert into @tbl (term_uid, xmldata)
    select term_uid , term_attributes from remoteServerLinkedName

select term_uid 
    , c.value('(Attribute[@name="C"]/text())[1]','varchar(100)') AS c
    , c.value('(Attribute[@name="D"]/text())[1]','varchar(100)') AS d
    , c.value('(Attribute[@name="F"]/text())[1]','varchar(100)') AS f
from @tbl as tbl 
    cross apply xmldata.nodes('Attributes[Attribute[@name="C"] 
        and Attribute[@name="D"] 
        and Attribute[@name="F"]]') AS c(c);
...