【问题标题】:xml explicit type attributexml 显式类型属性
【发布时间】:2018-03-23 23:02:26
【问题描述】:

我尝试结束我的 SQL 以获得提要输出...但我又遇到了一个复杂问题。首先,我要感谢我不是用于 XML 输出的 SQL 专家……但希望得到某人的帮助。

使用这个查询

SELECT 
    1487997 as ExternalId,
    'This is a name' as [Name]
INTO #sample

DROP TABLE #colors
SELECT 
    1487997 as ExternalId,
    'BV_FE_FAMILY:Green' as [Color]
INTO #colors
UNION 
SELECT
    1487997 as ExternalId,
    'Green' as [Color]

SELECT
    1 as Tag,
    NULL as Parent,
    NULL AS [EliminaTAG!1], -- empty root element
    NULL AS [Product!2!ExternalId!element],
    NULL AS [Product!2!Name!cdata],
    NULL AS [Product!2!]
UNION ALL
SELECT 
    2 AS Tag,
    1 AS Parent,
    NULL,
    ExternalId,  
    [Name],
    (
     SELECT  
       c.[Color] as Value
     FROM #colors  c 
     WHERE (ff.ExternalId = c.ExternalId)   
     FOR XML PATH('Attribute'), ROOT('Attributes'), TYPE)
FROM #sample ff 
FOR XML EXPLICIT

我已经接近我的范围...但我需要一个 id="BV_FE_FAMILY" 和 id="BV_FE_EXPAND" 进入 TAG...

<Attributes>
<Attribute id="BV_FE_FAMILY">
    <Value>Green</Value>
<Attribute>
<Attribute id="BV_FE_EXPAND">
    <Value>BV_FE_FAMILY:Green</Value>
<Attribute>
</Attributes>

我的结果是……错过“ID=.....”

    <EliminaTAG>
      <Product>
        <ExternalId>1487997</ExternalId>
        <Name><![CDATA[This is a name]]></Name>
        <Attributes xmlns="">
          <Attribute>
              <Value>Green</Value>
          </Attribute>
          <Attribute>
              <Value>BV_FE_FAMILY:Green</Value>
          </Attribute>
        </Attributes>
      </Product>
   </EliminaTAG>

感谢所有能给我正确建议的人。 意大利阿伦

【问题讨论】:

  • FOR XML EXPLICIT 是一个真正的头痛...您可能需要它的唯一原因是CDATA 部分。如果这不是外部强制要求,您应该使用FOR XML PATH 解决此问题。在语义上,CDATA 部分和正确转义的 normal text() 节点之间没有区别。

标签: sql xml attributes tags


【解决方案1】:

正如我在评论中指出的那样,FOR XML EXPLICIT 是一个相当笨拙的选择。但是有一些要求,否则无法解决...

所以,如果你真的需要这个,你可能会更容易解决:

SELECT
    1 as Tag,
    NULL as Parent,
    ff.ExternalId AS [Product!1!ExternalId!element],
    ff.Name AS [Product!1!Name!cdata],
    (
     SELECT  'SomeValueForId' AS [@id]
            ,c.Color AS [Value]
     FROM #colors c
     WHERE c.ExternalId=ff.ExternalId
     FOR XML PATH('Attribute'),ROOT('Attributes'),TYPE
    ) AS [Product!1!]
FROM #sample ff 
FOR XML EXPLICIT,ROOT('EliminaTAG');

结果

<EliminaTAG>
  <Product>
    <ExternalId>1487997</ExternalId>
    <Name><![CDATA[This is a name]]></Name>
    <Attributes xmlns="">
      <Attribute id="SomeValueForId">
        <Value>BV_FE_FAMILY:Green</Value>
      </Attribute>
      <Attribute id="SomeValueForId">
        <Value>Green</Value>
      </Attribute>
    </Attributes>
  </Product>
</EliminaTAG>

我不明白你的id 属性的内容来自哪里,这取决于你。

【讨论】:

    【解决方案2】:

    非常感谢您的帮助和建议... 我用你的代码解决了他的问题:

    SELECT
        1 as Tag,
        NULL as Parent,
        ff.ExternalId AS [Product!1!ExternalId!element],
        ff.Name AS [Product!1!Name!cdata],
        (
         SELECT  
                CASE
                    WHEN CHARINDEX('BV_FE_FAMILY', c.Color) > 0 THEN 'BV_FE_EXPAND' 
                    ELSE 'BV_FE_FAMILY'
                END AS [@id]
                ,c.Color AS [Value]
         FROM #colors c
         WHERE c.ExternalId=ff.ExternalId
         FOR XML PATH('Attribute'),ROOT('Attributes'),TYPE
        ) AS [Product!1!]
    FROM #sample ff 
    FOR XML EXPLICIT;
    

    这是我输出的结果

    <Product>
      <ExternalId>1487997</ExternalId>
      <Name><![CDATA[This is a name]]></Name>
      <Attributes xmlns="">
        <Attribute id="BV_FE_EXPAND">
          <Value>BV_FE_FAMILY:Green</Value>
        </Attribute>
        <Attribute id="BV_FE_FAMILY">
          <Value>Green</Value>
        </Attribute>
      </Attributes>
    </Product>
    

    可以删除这个 xmlns="" 吗? 目前,我将在 ETL 过程中将其删除,以便直接将 XML 文件创建到 SSIS 中......但如果有直接来自 T-SQL 的干净方式,我更喜欢...... 无论如何谢谢Shnugo! 阿伦

    P.S.:这是另一个使用(如您所说)FROM XML PATH 的版本,但是如何为某些元素插入 cdata?此选择已删除 xmlns=""...

    SELECT
        ff.ExternalId ,
        ff.Name,
        (
         SELECT  
                CASE
                    WHEN CHARINDEX('BV_FE_FAMILY', c.Color) > 0 THEN 'BV_FE_EXPAND' 
                    ELSE 'BV_FE_FAMILY'
                END AS [@id]
                ,c.Color AS [Value]
         FROM #colors c
         WHERE c.ExternalId=ff.ExternalId
         FOR XML PATH('Attribute'),ROOT('Attributes'),TYPE
        ) 
    FROM #sample ff 
    FOR XML PATH('Product'), ROOT('Products');
    

    这是我的最终解决方案(CAST + REPLACE + CAST):

    SELECT
        ff.ExternalId ,
        ff.Name,
        CAST(REPLACE(CAST((
         SELECT  
                CASE
                    WHEN CHARINDEX('BV_FE_FAMILY', c.Color) > 0 THEN 'BV_FE_EXPAND' 
                    ELSE 'BV_FE_FAMILY'
                END AS [@id]
                ,c.Color AS [Value]
         FROM #colors c
         WHERE c.ExternalId=ff.ExternalId
         FOR XML PATH('Attribute'),ROOT('Attributes'),TYPE
        )  as varchar(MAX)),' xmlns=""','') as xml)
    FROM #sample ff 
    FOR XML PATH('Product'), ROOT('Products');
    

    我的干净结果输出:

    <Products>
      <Product>
        <ExternalId>1487997</ExternalId>
        <Name>This is a name</Name>
        <Attributes>
          <Attribute id="BV_FE_EXPAND">
            <Value>BV_FE_FAMILY:Green</Value>
          </Attribute>
          <Attribute id="BV_FE_FAMILY">
            <Value>Green</Value>
          </Attribute>
        </Attributes>
      </Product>
    </Products>
    

    阿伦

    【讨论】:

    • xmlns="" 是一个众所周知且令人讨厌的问题。在子选择中使用FOR XML 将在您不想要它们的地方创建命名空间声明。这不是错误的,但会使您的 XML 膨胀,并且有时(严格的)模式验证会出现问题。转换为字符串和REPLACE 是一个很好的解决方法。
    • 关于CDATA。当您使用对VARCHAR 的转换(顺便说一句:最好使用NVARCHAR)并将其写回本机XML 时,CDATA 将消失。 SQL-Server 开发人员甚至决定不再支持这一点。实际上不需要CDATA...您的clean result output 没有CDATA。如果您可以没有,则根本不需要铸造和更换。在没有castreplace 的情况下尝试您自己的代码,没有xmlns="" 也可以 - 但也没有CDATA...
    • 是的,你的权利...我替换了更好的 nvarchar(max) 并删除到 REPLACE... 用双 CAST 似乎绝对完美。谢谢你的时间。非常感谢你。阿伦
    【解决方案3】:

    这是最终代码:

    SELECT
        ff.ExternalId ,
        ff.Name as Name,
        'http://www.mysite.it/imgege.jpg' as URL,
        CAST(CAST((
         SELECT  
                CASE
                    WHEN CHARINDEX('BV_FE_FAMILY', c.Color) > 0 THEN 'BV_FE_EXPAND' 
                    ELSE 'BV_FE_FAMILY'
                END AS [@id]
                ,c.Color AS [Value]
         FROM #colors c
         WHERE c.ExternalId=ff.ExternalId
         FOR XML PATH('Attribute'),ROOT('Attributes'),TYPE
        )  as nvarchar(MAX)) as xml)
    FROM #sample ff 
    FOR XML PATH('Product'), ROOT('Products');
    

    还有我的输出...

    <Products>
      <Product>
        <ExternalId>1487997</ExternalId>
        <Name>This is a name</Name>
        <URL>http://www.mysite.it/imgege.jpg</URL>
        <Attributes>
          <Attribute id="BV_FE_EXPAND">
            <Value>BV_FE_FAMILY:Green</Value>
          </Attribute>
          <Attribute id="BV_FE_FAMILY">
            <Value>Green</Value>
          </Attribute>
        </Attributes>
      </Product>
    </Products>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-19
      • 2016-02-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多