Estou procurando a solução limpa, elegante e inteligente para remover namespace de todos os elementos XML? Como funcionaria para fazer isso?
Interface definida:
public interface IXMLUtils
{
string RemoveAllNamespaces(string xmlDocument);
}
XML de amostra para remover NS de:
<?xml version="1.0" encoding="utf-16"?>
<ArrayOfInserts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<insert>
<offer xmlns="http://schema.peters.com/doc_353/1/Types">0174587</offer>
<type2 xmlns="http://schema.peters.com/doc_353/1/Types">014717</type2>
<supplier xmlns="http://schema.peters.com/doc_353/1/Types">019172</supplier>
<id_frame xmlns="http://schema.peters.com/doc_353/1/Types" />
<type3 xmlns="http://schema.peters.com/doc_353/1/Types">
<type2 />
<main>false</main>
</type3>
<status xmlns="http://schema.peters.com/doc_353/1/Types">Some state</status>
</insert>
</ArrayOfInserts>
Depois de chamarmos RemoveAllNamespaces (xmlWithLotOfNs), devemos obter:
<?xml version="1.0" encoding="utf-16"?>
<ArrayOfInserts>
<insert>
<offer >0174587</offer>
<type2 >014717</type2>
<supplier >019172</supplier>
<id_frame />
<type3 >
<type2 />
<main>false</main>
</type3>
<status >Some state</status>
</insert>
</ArrayOfInserts>
A linguagem preferida da solução é C # no .NET 3.5 SP1.
Respostas:
Bem, aqui está a resposta final. Usei uma ótima ideia do Jimmy (que infelizmente não é completa) e a função de recursão completa para funcionar corretamente.
Com base na interface:
Eu represento aqui a solução C # final limpa e universal para a remoção de namespaces XML:
Está funcionando 100%, mas não testei muito então pode não abranger alguns casos especiais ... Mas é uma boa base para começar.
fonte
A resposta marcada mais útil tem duas falhas:
Aqui está minha opinião sobre isso:
Amostra de código aqui .
fonte
xmlns
também.(from a in e.Attributes().DistinctBy(x => x.Name.LocalName)
para o casolang=""ru-ru"" xml:lang=""ru-ru""
a resposta obrigatória usando LINQ:
fonte
Isso será o suficiente :-)
fonte
Pegue-o novamente, em C # - linha adicionada para copiar os atributos:
fonte
A resposta obrigatória usando XSLT:
fonte
E esta é a solução perfeita que também removerá elementos XSI. (Se você remover os xmlns e não remover o XSI, o .Net grita com você ...)
fonte
Regex.Replace(xmlStr, @"<(/?)([^>\s:]+):([^>]+)>", "<$1$3>")
Sei que esta questão está supostamente resolvida, mas não fiquei totalmente satisfeito com a forma como foi implementada. Eu encontrei outra fonte aqui nos blogs do MSDN que tem uma
XmlTextWriter
classe substituída que remove os namespaces. Eu ajustei um pouco para obter algumas outras coisas que queria, como formatação bonita e preservação do elemento raiz. Aqui está o que tenho no meu projeto no momento.http://blogs.msdn.com/b/kaevans/archive/2004/08/02/206432.aspx
Classe
Uso
fonte
Esta é uma solução baseada na resposta aceita de Peter Stegnar.
Eu o usei, mas (como andygjp e John Saunders observaram) seu código ignora atributos .
Eu precisava cuidar dos atributos também, então adaptei seu código. A versão de Andy era Visual Basic, ainda é c #.
Eu sei que já faz um tempo, mas talvez isso poupe algum tempo um dia.
fonte
Eu realmente gostei de onde Dexter está indo, então eu traduzi em um método de extensão “fluente”:
A abordagem “fluente” me permite fazer isso:
fonte
Você pode fazer isso usando o Linq:
fonte
A resposta de Peter ligeiramente modificada, funcionaria bem para o atributo também, incluindo a remoção do namespace e do prefixo. Um pouco triste, o código parece um pouco feio.
fonte
A resposta de Jimmy e Peter foi de grande ajuda, mas eles removeram todos os atributos, então fiz uma pequena modificação:
fonte
Um pouco tarde para a festa, mas aqui está o que usei recentemente:
(retirado deste Tópico MSDN )
Editar Conforme o comentário abaixo, parece que embora isso remova o prefixo de namespace dos nós, na verdade não remove o atributo xmlns. Para fazer isso, você também precisa redefinir o nome de cada nó para seu nome local (por exemplo, nome menos namespace)
fonte
Para que os atributos funcionem, o loop for para adicionar o atributo deve ocorrer após a recursão, também é necessário verificar se IsNamespaceDeclaration:
fonte
Aqui está minha versão VB.NET do Dexter Legaspi C # Version
fonte
Outra solução que leva em consideração a possibilidade de intercalar os nós TEXT e ELEMENT, por exemplo:
Código:
fonte
Sem recorrer a uma solução baseada em XSLT, se você quiser limpo, elegante e inteligente, precisará de algum suporte do framework, em particular, o padrão do visitante pode tornar isso uma brisa. Infelizmente, não está disponível aqui.
Eu o implementei inspirado no LINQ
ExpressionVisitor
para ter uma estrutura semelhante a ele. Com isso, você pode aplicar o padrão de visitante a objetos XML (LINQ-to-). (Fiz testes limitados, mas funciona bem, pelo que posso dizer)ps, esta implementação particular usa alguns recursos do .NET 4 para tornar a implementação um pouco mais fácil / limpa (uso de
dynamic
e argumentos padrão). Não deve ser muito difícil torná-lo compatível com .NET 3.5, talvez até compatível com .NET 2.0.Então, para implementar o visitante, aqui está um generalizado que pode alterar vários namespaces (e o prefixo usado).
E um pequeno método auxiliar para fazer a bola rolar:
Então, para remover um namespace, você poderia chamá-lo assim:
Usando este visitante, você pode escrever um
INamespaceMappingManager
para remover todos os namespaces.fonte
Solução simples que realmente renomeia os elementos no local, sem criar uma cópia, e faz um bom trabalho ao substituir os atributos.
Observação: isso nem sempre preserva a ordem original dos atributos, mas tenho certeza de que você pode alterá-la para fazer isso facilmente se for importante para você.
Observe também que isso também pode gerar uma exceção, se você tiver atributos de XElement que são exclusivos apenas com o namespace, como:
o que realmente parece ser um problema inerente. Mas, como a questão indicava a saída de uma String, não um XElement, neste caso você poderia ter uma solução que geraria uma String válida que era um XElement inválido.
Também gostei da resposta de jocull usando um XmlWriter personalizado, mas quando tentei, não funcionou para mim. Embora tudo pareça correto, não pude dizer se a classe XmlNoNamespaceWriter teve algum efeito; definitivamente não estava removendo os namespaces como eu queria.
fonte
Adicionar my também limpa o nome dos nós que têm prefixos de namespace:
fonte
Tentei as primeiras soluções e não funcionou para mim. Principalmente o problema com os atributos sendo removidos como os outros já mencionados. Eu diria que minha abordagem é muito semelhante à de Jimmy, usando os construtores XElement que usam objetos como parâmetros.
fonte
minha resposta, baseada em manipulação de strings,
código mais leve,
fonte
Aqui estão Regex Replace one liner:
Aqui está um exemplo: https://regex101.com/r/fopydN/6
Aviso: pode haver casos extremos!
fonte
A resposta do usuário892217 está quase correta. Ele não compilará como está, então precisa de uma ligeira correção para a chamada recursiva:
fonte
Isso funcionou para mim.
fonte
Depois de muito procurar por uma solução para esse problema, esta página em particular parecia ter mais problemas ... no entanto, nada se encaixava exatamente, então peguei o método antigo e apenas analisei o que eu queria. Espero que isso ajude alguém. (Observação: isso também remove o SOAP ou material de envelope semelhante.)
fonte
Sem recriar toda a hierarquia de nós:
fonte
Eu tentei algumas das soluções, mas como afirmado por muitos, existem alguns casos extremos.
Usou algumas das regexes acima, mas chegou à conclusão de que uma regex de uma etapa não é viável.
Portanto, aqui está minha solução, regex de 2 etapas, localizar tags, remover tags, não alterar cdata:
Por enquanto está 100% funcionando para mim.
fonte
Aqui está uma solução baseada em regex para este problema ...
fonte
Acho que esta é a resposta mais curta (mas para construções como, você terá outra discussão, eu também tenho regex para converter
"<bcm:info></bcm:info>"
para "<info></info>
" mas não foi otimizado, se alguém me perguntar eu compartilharei. Então, minha solução é:fonte