Como analiso e escrevo XML usando o ElementTree do Python sem mover espaços de nome?

Nosso projeto obtém do XML upstream deste formulário:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="7.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <appSettings>
    <add key="foo" value="default">
    ...
  </appSettings>
</configuration>

Em seguida, ele lê / analisa esse XML usando o ElementTree e, para cada configuração de aplicativo que corresponde a uma determinada chave ("foo"), grava um novo valor queisto sabe que o processo upstream não funciona (nesse caso, a chave "foo" deve ter o valor "bar").

oRio abaixo processo consumindo o XML filtrado é, aaahhhh ...frágil. Ele espera receber o XML emexatamente o formulário acima.

Se eu analisar esse XML sem registrar um espaço para nome, o ElementTree manipulará minha árvore como esta na entrada:

<configuration xmlns:ns0="urn:schemas-microsoft-com:asm.v1">
  <runtime>
  <ns0:assemblyBinding>
    <ns0:dependentAssembly>
      <ns0:assemblyIdentity culture="neutral" name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" />
      <ns0:bindingRedirect newVersion="7.0.0.0" oldVersion="0.0.0.0-6.0.0.0" />
    </ns0:dependentAssembly>
  </ns0:assemblyBinding>
 </runtime>
 <appSettings>
    <add key="foo" value="default">
    ...
 </appSettings>
</configuration>

O processo a jusante não pode lidar com isso, porque não é inteligente o suficiente para perceber que, semanticamente, isso é a mesma coisa. Então, decido registrar o espaço para nome que sei que o processo upstream fornecerá como espaço para nome padrão para evitar que os prefixos apareçam em todos os lugares e agora entendi:

<configuration xmlns="urn:schemas-microsoft-com:asm.v1">
 <runtime>
  <assemblyBinding>
    <dependentAssembly>
      <assemblyIdentity culture="neutral" name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" />
      <bindingRedirect newVersion="7.0.0.0" oldVersion="0.0.0.0-6.0.0.0" />
    </dependentAssembly>
  </assemblyBinding>
 </runtime>
 <appSettings>
    <add key="foo" value="default">
    ...
 </appSettings>
</configuration>

Eu não sei muito sobre XML, mas esse também o componente downstream chora, e parece-me que agora não significa esse padrãoxmlns agora aplique atudo elementos incluídos dentro<configuration>, enquanto que antessó aplicado ao<assemblyBinding> elemento?

Existe alguma maneira,usando ElementTree, para manipular esse espaço de nome para que eu possa absorver o XML do upstream, definafooé o valor e, em seguida, passa-o a jusante, sem mover o espaço para nome e deixá-lo exatamente como o encontrei?

Eu poderia usar uma solução baseada em lxml, que parece lidar com isso,Contudo, lxml depende de C, que o componente downstream realmente gostaria de não ter suporte: é preferível uma solução Python pura.

Eu poderia ler o documento como HTML, o que ignoraria o atributo de espaço para nome, deixe-me manipular o valor desejado e depois passar o documento;Contudo, Ainda não encontrei um analisador Python que não faça o downcase de todos os nomes de elementos, e meu componente downstream exige que a cobertura de todos os nomes de elementos seja preservada.

Eu poderia recorrer à análise de strings e a expressões regulares. Prefiro não escrever meu próprio analisador.

O único conselho que pude encontrar até agora sobre o tratamento de namespace no ElementTree sugere a abordagem "registrar um namespace padrão para evitar prefixos", que eu supunha que seria adequado, mas o ElementTree insiste em mover oxmlns declaração até o nó raiz após o dumping.

Eu também poderia ser inteligente construindo uma corda que despeja a árvore em estágios e na ordem exata para colocar oxmlns declaração de volta no "nó direito", mas isso me parece também muito frágil.

Alguém conseguiu superar um problema como este?

questionAnswers(0)

yourAnswerToTheQuestion