Search code examples
javaxmlparsingmessageformat

MessageFormat parse error when parsing a non English message


My application validates XML based on XSD files. The result of this validation is a error message. To show this for users, I parse this error message using java.text.MessageFormat. The problem is: when the message comes in English I'm able to parse it normally, but when the message comes in Portuguese (Brazil) it returns the error below:

java.text.ParseException: MessageFormat parse error!
    at java.text.MessageFormat.parse(MessageFormat.java:1035)
    at com.local.messageformat.MessageFormatMain.splitMessage(MessageFormatMain.java:34)
    at com.local.messageformat.MessageFormatMain.start(MessageFormatMain.java:20)
    at com.local.messageformat.MessageFormatMain.main(MessageFormatMain.java:14)

Here is my code:

public class MessageFormatMain {

public static void main(String[] args) {
    final MessageFormatMain main = new MessageFormatMain();
    main.start();
}

private void start() {
    final String errorMessageKey = "cvc-complex-type.2.4.a";
//Portuguese message (shows error)
    final String errorMessage = "cvc-complex-type.2.4.a: Conteúdo inválido encontrado a partir do elemento 'inscricaomunicipaltomador'. Um de '{razaosocialtomador, estrangeirotomador, tipologradourotomador, logradourotomador, numeroenderecotomador, bairrotomador, complementotomador, cidadetomadordescricao, estadotomadordescricao, fonetomador, ceptomador, emailtomador, tomadorpais, tomadorresptribut, codigoatividade, aliquotaatividade, tiporecolhimento, valortotalrps, valorservicosrps, valoriss, valorpis, valorcofins, valorinss, valorir, valorcsll, aliquotapis, aliquotacofins, aliquotainss, aliquotair, aliquotacsll, descricaorps, tributacaorps, localservico, itens}' é esperado.";
// English message (works fine)
//  final String errorMessage = "cvc-complex-type.2.4.a: Invalid content was found starting with element 'inscricaomunicipaltomador'. One of '{razaosocialtomador, estrangeirotomador, tipologradourotomador, logradourotomador, numeroenderecotomador, bairrotomador, complementotomador, cidadetomadordescricao, estadotomadordescricao, fonetomador, ceptomador, emailtomador, tomadorpais, tomadorresptribut, codigoatividade, aliquotaatividade, tiporecolhimento, valortotalrps, valorservicosrps, valoriss, valorpis, valorcofins, valorinss, valorir, valorcsll, aliquotapis, aliquotacofins, aliquotainss, aliquotair, aliquotacsll, descricaorps, tributacaorps, localservico, itens}' is expected.";
    Object[] ret = splitMessage(errorMessage, errorMessageKey);
    if (ret.length > 0) {
        System.out.println(ret[0]);
        System.out.println(ret[1]);
    }
}

private Object[] splitMessage(final String errorMessage, final String errorMessageKey) {
    final ResourceBundle resourceBundle = PropertyResourceBundle.getBundle("com.sun.org.apache.xerces.internal.impl.msg.XMLSchemaMessages", Locale.ROOT);
    if (errorMessageKey != null && !errorMessageKey.isEmpty() && resourceBundle.containsKey(errorMessageKey)) {
        final String errorMessagePattern = resourceBundle.getString(errorMessageKey);
        final MessageFormat messageFormat = new MessageFormat(errorMessagePattern);
        Object arguments[];
        try {
            arguments = messageFormat.parse(errorMessage);
            return arguments;
        } catch (final ParseException e) {
            e.printStackTrace();
        }
        return new Object[0];
    }
    return new Object[0];
}

}

I've tried to specify a different location to get de ResourceBundle and even to instantiate the MessageFormat, but non of them worked.

Thanks in advance.

Guilherme


Solution

  • I figured out the solution for this problem. In a first moment I do a XSD schema validation of the XML file using the XercesImpl lib, wich uses the following package:

    org.apache.xerces.impl.msg.XMLSchemaMessages
    

    Firstly the message loaded was in English, but after an update of this lib the message loaded is in Portuguese. Then, when the splitMessage method was called I was referencing the Java package instead of the XercesImpl package. Obviously, the MessageFormat.parse was unable to parse a Portuguese message (extracted from XercesImpl) using the English message (extracted from Java package).

    To solve this I made a simple change in splitMessage method. Like this:

    final ResourceBundle resourceBundle = ResourceBundle.getBundle("org.apache.xerces.impl.msg.XMLSchemaMessages");
    

    Remembering that I set the Locale as "PT/BR" in the main method, that's why I don't have to set the Locale to load the resource.

    The funny part is that there is the Portuguese schema message files in the JDK that I am using. So, it should have worked anyway.