SQL 中 XML 命名空间的重复

Posted

技术标签:

【中文标题】SQL 中 XML 命名空间的重复【英文标题】:Duplication of XML namespaces in SQL 【发布时间】:2017-12-01 17:50:08 【问题描述】:

我有以下问题,我需要删除“cfdi:”的“cfdi_”

我使用命名空间来解决这个问题,但是它们被每个节点重复,我无法消除它们,如果你能帮助我,我将不胜感激

declare @Mydoc xml;

set @Mydoc = (SELECT 
                  '' as importe,
                  (SELECT Importe, TasaCuota, TipoFactor, Impuesto, Base
                   FROM CDFIDet
                   FOR XML RAW('cfdi_traslado'), TYPE, ROOT('cfdi_traslados'))
              FROM
                  CFDIENC
              FOR XML RAW('cfdi_gatito'),type)

SELECT @Mydoc;

结果1:

<cfdi:gatito importe="">
  <cfdi:traslados>
    <cfdi:traslado Importe="1920" TasaCuota="0" TipoFactor="Tasa" Impuesto="16" Base="240" />
    <cfdi:traslado Importe="2202" TasaCuota="0" TipoFactor="TASA" Impuesto="16" Base="450" />
  </cfdi:traslados>
</cfdi:gatito>

第二次尝试:

declare @Mydoc xml;

WITH xmlnamespaces ('uri' as cfdi)
    SELECT @Mydoc = (SELECT 
                         '' AS importe,
                         (SELECT Importe, TasaCuota, TipoFactor, Impuesto, Base
                          FROM CDFIDet
                          FOR XML RAW('cfdi:traslado'), TYPE, ROOT('cfdi:traslados'))
                     FROM CFDIENC
                     FOR XML RAW('cfdi:gatito'), TYPE)

SELECT @Mydoc;

结果:

<cfdi:gatito xmlns:cfdi="uri" importe="">
  <cfdi:traslados xmlns:cfdi="uri">
    <cfdi:traslado Importe="1920" TasaCuota="0" TipoFactor="Tasa" Impuesto="16" Base="240" />
    <cfdi:traslado Importe="2202" TasaCuota="0" TipoFactor="TASA" Impuesto="16" Base="450" />
  </cfdi:traslados>
</cfdi:gatito>

我的代码比较大,重复次数太多不知道怎么消除

【问题讨论】:

XML 支持高度特定于供应商 - 所以请添加一个标签来指定您是否使用mysqlpostgresqlsql-serveroracledb2 - 或完全不同的东西。 这是 sql server 但我不会让你放那个标签,因为我还是新手 那么想要的结果是什么? 第一个结果 【参考方案1】:

这是令人讨厌但有效的输出...每个带有FOR XML 语句的子选择都将添加自己的一组命名空间声明。有一个很古老的——但被忽视了! - Microsoft Connect issue去那里投票吧。

没有真正的解决方法,只有一些技巧。大多数人最终在字符串级别上遇到了一些丑陋的技巧。在这种情况下,您可以创建没有任何命名空间的 XML,并在完成后使用字符串方法对其进行更改。

在您的另一个问题中,您有想法将前缀添加到您的别名中,例如 cfdi_Element 并稍后将其更改为 cfdi:Element

这正是我要说的......

但再说一遍:这并没有错,只是让你的输出烦人和臃肿......

试试这个: 声明@Mydoc xml;

WITH xmlnamespaces ('uri' as cfdi)
SELECT @Mydoc = (SELECT 
                        'SomeValue' AS OuterElement,
                        (SELECT 'OtherValue' AS InnerElement
                        FOR XML RAW('cfdi:traslado'), TYPE)
                    FOR XML RAW('cfdi:gatito'), TYPE)

--命名空间声明被复制

SELECT @Mydoc;

<cfdi:gatito xmlns:cfdi="uri" OuterElement="SomeValue">
  <cfdi:traslado xmlns:cfdi="uri" InnerElement="OtherValue" />
</cfdi:gatito>

--但在这里它“有效”

SELECT @Mydoc = (SELECT 
                        'SomeValue' AS OuterElement,
                        (SELECT 'OtherValue' AS InnerElement
                        FOR XML RAW('cfdi_traslado'), TYPE)
                    FOR XML RAW('cfdi_gatito'), TYPE)

--转换为NVARCHAR(MAX),将ns-decl 放入根节点并进行一些替换:

SELECT CAST(REPLACE(REPLACE(CAST(@Mydoc AS NVARCHAR(MAX)),'<cfdi_gatito','<cfdi_gatito xmlns:cfdi="uri"'),'cfdi_','cfdi:') AS XML);

<cfdi:gatito xmlns:cfdi="uri" OuterElement="SomeValue">
  <cfdi:traslado InnerElement="OtherValue" />
</cfdi:gatito>   

这很丑陋,但通常是唯一的机会......

【讨论】:

你是我的 ECHO 英雄 这更简单,它添加了让我错过真相的节点,你非常感谢,你是我的英雄【参考方案2】:

从 XML 预期来看,第二个结果是自给自足的 XML 元素,而第一个结果只能是定义了 cfdi 前缀的命名空间的其他元素的一部分。 所以,我猜所有的作品都如你所定义。

子选择

(SELECT Importe, TasaCuota, TipoFactor, Impuesto, Base
                      FROM CDFIDet
                      FOR XML RAW('cfdi:traslado'), TYPE, ROOT('cfdi:traslados'))

产生自给自足的结果

<cfdi:traslados xmlns:cfdi="uri">
   <cfdi:traslado Importe="1920" TasaCuota="0" TipoFactor="Tasa" Impuesto="16" Base="240" />
   <cfdi:traslado Importe="2202" TasaCuota="0" TipoFactor="TASA" Impuesto="16" Base="450" />
</cfdi:traslados>

因为您定义了ROOT('cfdi:traslados') - 其中有命名空间,而嵌套元素 cfdi:traslado 位于同一个命名空间中 - 没有单独的命名空间声明。

然后顶部选择:

 SELECT 
   '' AS importe,
   (SELECT Importe, TasaCuota, TipoFactor, Impuesto, Base
      FROM CDFIDet
           FOR XML RAW('cfdi:traslado'), TYPE, ROOT('cfdi:traslados'))
 FROM CFDIENC
   FOR XML RAW('cfdi:gatito'), TYPE)

cfdi:traslados 的根元素定义为cfdi:gatito 它有自己的 cfdi 前缀命名空间声明。

我不熟悉 sql-server XML,但是如果你删除会发生什么 ROOT('cfdi:traslados') 来自子选择? 它会从 &lt;cfdi:traslados xmlns:cfdi="uri"&gt; 元素中删除 xmlns:cfdi="uri" 吗?

【讨论】:

一个计费的一般一个 xml 和多个需要特定格式的问题,如果我声明名称空间,我对每个节点都有宣传,我需要把所有内容都放在上面,但只替换“cfdi_ " 与 "cfdi:" 对不起,我的问题仍然不清楚...从技术上讲,如果在 &lt;cfdi:gatito importe=""&gt; 顶部的 Result1 根元素(最近的一个)中将 cfdi 前缀的命名空间声明为 @987654335,则两个结果都是相同的@. 很容易兄弟,看我需要 xsi 出来:schemaLocation 和 xmlns: cfdi 但是使用命名空间我不能声明前缀 xsi 因为 xmlns 是重叠的,除此之外我在每个中生成它节点命名空间被放置,我无法消除

以上是关于SQL 中 XML 命名空间的重复的主要内容,如果未能解决你的问题,请参考以下文章

从 XML 中删除多个 XML 命名空间

XSLT 匹配和命名空间 [重复]

如何使用 Jackson 处理命名空间重复的 xml 标签

未在 XSLT 中引用默认命名空间 [重复]

XML名命空间

使用 SimpleXML 使用命名空间解析 XML [重复]