Duplication of XML namespaces in SQL

后端 未结 2 1336
遥遥无期
遥遥无期 2021-01-25 00:46

I have the following problem, I need to remove the \"cfdi_\" for \"cfdi:\"

I used the namespaces to solve that but they are duplicated by each node and I can not elimina

相关标签:
2条回答
  • 2021-01-25 01:09

    It is annoying but valid output... Each sub-select withing a FOR XML statement will add its own set of namespace declarations. There is a very old - yet ignored! - Microsoft Connect issue Go there and vote for it.

    There is no real workaround, just some hacks. Most people end up with some ugly tricks on string level. In this case you create the XML without any namespace and change it with string methods when you are finished.

    In your other question you had the idea to add the prefix to your aliases like cfdi_Element and change this to cfdi:Element later.

    This is exactly what I'm talking about...

    But once again: It is not wrong, just annoying and bloating your output...

    Try this: declare @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)
    

    --The namespace declaration is replicated

    SELECT @Mydoc;
    
    <cfdi:gatito xmlns:cfdi="uri" OuterElement="SomeValue">
      <cfdi:traslado xmlns:cfdi="uri" InnerElement="OtherValue" />
    </cfdi:gatito>
    

    --But here it "works"

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

    --A cast to NVARCHAR(MAX), the ns-decl into the root node and some replaces:

    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>   
    

    This is ugly, but often the only chance...

    0 讨论(0)
  • 2021-01-25 01:16

    From XML prospective second result is self-sufficient XML element, while first result can be only part of other element where namespace for cfdi prefix is defined. So, I guess all works as you defined.

    Sub-select

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

    produces self-sufficient result as

    <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>
    

    because you defined ROOT('cfdi:traslados') - you have namespace in it, and nested elements cfdi:traslado are in the same namespace - there is no separate namespace declaration.

    Then top select:

     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)
    

    defines a root element for cfdi:traslados as cfdi:gatito it has its own namespace declaration for cfdi prefix.

    I'm not familiar with sql-server XML, but what will happen if you remove ROOT('cfdi:traslados') from sub-select? Will it remove xmlns:cfdi="uri" from <cfdi:traslados xmlns:cfdi="uri"> element?

    0 讨论(0)
提交回复
热议问题