Codificando XML usando a codificação ASCII em vez de entidades de personagem
-
23-09-2019 - |
Pergunta
Tudo bem, então aqui está o meu problema. Preciso gerar XML em Java para passar para outro aplicativo. Comecei a pensar que isso seria fácil usando um org.w3c.dom.document. Infelizmente, o aplicativo que eu preciso passar o XML exige que caracteres especiais como "precisam ser codificados como ASCII (") em vez de sua entidade de personagem ("). Alguém conhece uma solução simples para isso?
PS Alterar o aplicativo de destino não é uma opção.
ATUALIZAÇÃO: Então, digamos que meu aplicativo receba a seguinte string como entrada:
he will "x" this if needed
Meu aplicativo precisa produzir isso:
<field value="he will "x" this if needed"/>
O gerador XML que estou usando e acho que a maioria dos outros produz isso, mas isso não é válido para o meu alvo:
<field value="he will "x" this if needed"/>
Sei que meu alvo pode não estar de acordo com os padrões XML, mas isso não me ajuda, pois não tenho controle sobre isso. Esta é a minha situação e tenho que lidar com isso. Alguma idéia além de simplesmente converter todos os personagens especiais à mão?
Solução
Eu me pergunto como você serializa o XML-a uma string, um fluxo, etc. Você pode pós-processo de sua saída para substituir as referências de entidade geral por seus equivalentes numéricos, por exemplo,
sed 's/</\</g; s/>/\>/g; s/&/\&/g; s/'/\'/g; s/"/\"/g'
ou
xmlResultString.replaceAll("<", "<"); //etc. for other entities
Existem exatamente 5 entidades gerais predefinidas em XML (http://www.w3.org/tr/rec-xml/#sec-predefined-ent) e você pode executar com segurança isso como uma substituição textual. Não há perigo que ele modifique qualquer coisa, exceto as referências (bem, talvez em comentários e pis, mas não parece que seu cenário as use ou que o alvo os aceite).
Concordo com Mark que seu aplicativo de destino não é um processador XML em conformidade. Pelo menos vem com documentação que afirma explicitamente onde diverge do XML. Acredito que a recomendação (link acima) discorde do comentário de Christopher, embora seja irrelevante à pergunta de OP, pois seu alvo declara sua não conformidade à recomendação.
Ari.
Outras dicas
Que eu saiba, a API padrão não expõe o mecanismo de escape. Você provavelmente precisaria escrever seu próprio emissor XML.
Se você não se importa com uma API de terceiros, você pode usar JDOM. Algo como:
XMLOutputter outputter = new XMLOutputter() {
@Override
public String escapeAttributeEntities(String sequence) {
// TODO: bug: code only works for Basic Multilingual Plane
StringBuilder out = new StringBuilder();
for (int i = 0; i < sequence.length(); i++) {
process(sequence.charAt(i), out);
}
return out.toString();
}
private void process(char codePoint, StringBuilder out) {
if (codePoint == '"' || codePoint == '\'' || codePoint == '&'
|| codePoint == '<' || codePoint == '>' || codePoint > 127) {
out.append("&#");
out.append(Integer.toString(codePoint));
out.append(";");
} else {
out.append(codePoint);
}
}
};
outputter.setFormat(Format.getPrettyFormat().setEncoding("US-ASCII"));
Element foo = new Element("foo").setAttribute("msg",
"he will \"x\" this if needed");
Document doc = new Document().setRootElement(foo);
outputter.output(doc, System.out);
Isso emite:
<?xml version="1.0" encoding="US-ASCII"?>
<foo msg="he will "x" this if needed" />
(Eu ainda daria o XML Spec uma vez antes de fazer isso e consertar o manuseio de personagens para apoiar os personagens acima de u+ffff.)