【问题标题】:get all attributes from nodes with same name从具有相同名称的节点获取所有属性
【发布时间】:2016-07-05 05:18:45
【问题描述】:

我有一个包含产品的 xml 文件。 我已将其拆分为一个表,其中每个产品都有一行,其中包含产品编号和 xml

SKU |  xml
----|-------
1111|<product><price>123</price....</product>
1112|<product><price>345</price....</product>

属性是这样存储的:

<attribute-list>
    <attribute name="tax_id" attribute-type="integer"><value default="1">2</value></attribute>
        <attribute name="weight" attribute-type="integer"><value default="1">258</value></attribute>
        <attribute name="length" attribute-type="integer"><value default="1">180</value></attribute>
        <attribute name="width" attribute-type="integer"><value default="1">115</value></attribute>
        <attribute name="height" attribute-type="integer"><value default="1">15</value></attribute>
        <attribute name="series_name" attribute-type="string"><value language-id="DE" default="1"><![CDATA[CSV]]></value></attribute>
        <attribute name="country_of_origin_code" attribute-type="string"><value default="1">LT</value></attribute>
        <attribute name="number_of_pages" attribute-type="string"><value default="1">288</value></attribute>
...
</attribute-list>

不同的产品可能有不同的属性,例如鞋码与一本书无关:-)

我想选择所有可能的属性名。

attr
----
weight
length
number_of_pages
shoe_size

我可以获得给定属性名的所有可能值

select distinct xml.value('(/product/attribute-list/attribute[@name="color"])[1]',
'varchar(100)') as colors from product_xml

我已经接近了

 SELECT distinct cast(T2.attr.query('.') as nvarchar(max))
 FROM   product_xml
 CROSS APPLY xml.nodes('/product/attribute-list/attribute') as T2(attr) 

在这里我得到了每个可能的属性名称和值的记录

所以我只是错过了仅获取名称的最后一步。

编辑:快速和肮脏的版本在这里:

;with p as (SELECT distinct cast(T2.attr.query('.') as nvarchar(max)) at
FROM   product_xml
CROSS APPLY xml.nodes('/product/attribute-list/attribute') as T2(attr)) 
select distinct left(at,CHARINDEX('>',at)) from p

这会自行生成记录中的每个属性,然后我可以在应用程序 (php) 中对其进行操作,不像单独获取名称那样干净,但易于解析,并且很少使用。

<attribute name="age_rating" attribute-type="string">
<attribute name="aroma" attribute-type="string">
<attribute name="barcode" attribute-type="string">
<attribute name="barcode_type" attribute-type="string">

【问题讨论】:

    标签: sql-server xml


    【解决方案1】:

    这就是你要找的吗?该语句列出了每个属性的所有@name 属性,然后还从&lt;Value&gt; 子节点中获取了实际的Value 以及@DefaultValue

    SELECT DISTINCT   
        AttrName = XC.value('@name', 'varchar(50)'),
        DefaultValue=XC.value('(value/@default)[1]', 'varchar(50)'),
        Value=XC.value('(value)[1]', 'varchar(50)')
    FROM
        product_xml
    CROSS APPLY
        xml.nodes('/product/attribute-list/attribute') AS XT(XC)
    

    这向我展示了类似的东西:

    【讨论】:

    • 不完全是,因为我只需要唯一的 AttrName,我需要处理应用程序中的每个属性名称:foreach attrname,将其插入 shop,获取 attrname_id,foreach 该 attrname 的值插入它带着那个 attrname_id 进入商店但是你的建议让我找到了解决方案,所以我会接受它作为答案。
    • 另外,我需要手动处理属性,因为有些是商店眼中的属性,例如可以区分变化的 shoe_size,有些是客户没有选择的重量等特征开,有些根本不用
    【解决方案2】:

    基于@mark_s的解决方案

    SELECT distinct AttrName = attr.value('@name', 'varchar(50)') 
    FROM   product_xml
    CROSS APPLY xml.nodes('/product/attribute-list/attribute') as T2(attr) 
    

    【讨论】: