use Locale to display information from XML


I have a XML file and a XSL file. A java file reads info from the xml file and diplays it in the JEditorPane.  
i want that information should be dispalyed according to Locale.
the XML file is soemthing like

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="window.xsl"?>

    <doc>
     <title>
       <string lang="en">1</string>
       <string lang="fr">2</string>
     </title>
     <body>
       <val>
          <string lang="en">3</string>
          <string lang="fr">4</string>
       </val>
       <val>
          <string lang="en">5</string>
          <string lang="fr">6</string>
       </val>
    </body>
    </doc>

So when the Locale is "en" 1, 3 and 5 should be displayed and when locale is "fr" 2, 4, 6 should be displayed.
Here is the xsl file

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="/">
  <html>
  <body>
   <h2><xsl:value-of select="doc/title"/></h2>

   <table border="1">
      <xsl:for-each select="doc/body/val">
      <tr>
           <xsl:for-each select="string">
              <td><xsl:value-of select="."/></td>
          </xsl:for-each>
      </tr>
     </xsl:for-each>
   </table>

  </body>
  </html>
 </xsl:template>
</xsl:stylesheet>

this is part of the java file


 private static void show(String windowPath) {
    /**Bundle to read the panel specific file*/
    ResourceBundle resource;
    try {
      JFrame f = new JFrame();
      f.setLocation( -1000, -1000);
      safetyWindow = new SafetyWindow();
      resource = ResourceBundle.getBundle(SystemConstants.PATH +
                                          windowPath, Language.getLocale());

      String title = resource.getString("title");


      safetyWindow.setTitle(title);
      htmlPage = new JEditorPane();
      htmlPage.setContentType("text/html");
      htmlPage.setEditable(false);
      TransformerFactory factory = TransformerFactory.newInstance();

      Templates template = factory.newTemplates(new StreamSource(
          new FileInputStream(SystemConstants.PATH +
                              windowPath + ".xsl")));

      Transformer xformer = template.newTransformer();

      Source source = new StreamSource(new FileInputStream(SystemConstants.PATH +
          windowPath + ".xml"));
   // gives Locale
      System.out.println("Locale: "+Language.getLocale());

      // Apply the xsl file to the source file and write the result to the output file
      StreamResult result = new StreamResult(new StringWriter());
      xformer.transform(source, result);
      StringWriter writer = (StringWriter) result.getWriter();
      htmlPage.setText( (writer.getBuffer()).toString());

      JScrollPane scrollPane = new JScrollPane(htmlPage);
      safetyWindow.getContentPane().add(scrollPane, BorderLayout.CENTER);

    }
    catch (Exception exp) {
      logger.fatal("showWindow():Exception" + exp);
    }

    JPanel jPanel = new JPanel();
    jPanel.setBackground(Color.lightGray);
    okBtn = new JButton(Language.getMessage("Done"));
    jPanel.add(okBtn);
    okBtn.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent ae) {
        safetyWindow.setVisible(false);
        safetyWindow.dispose();

      }
    });
    safetyWindow.getContentPane().add(jPanel, BorderLayout.SOUTH);
    Dimension screenSize = safetyWindow.getToolkit().getScreenSize();
    int width = screenSize.width * 8 / 20;
    int height = screenSize.height * 8 / 20;
    safetyWindow.setBounds(width / 8, height / 8, width, height);
    safetyWindow.setVisible(true);
    safetyWindow.toFront();

  }
LVL 8
thomas908Asked:
Who is Participating?
 
ramazanyichCommented:
The simpliest way will be using xsl:param in your stylesheet and provide parameter value based on Locale to your transformation. If you need I will  send an example
0
 
expertmbCommented:
instead of xml you can use the properties file for each locale.
0
 
thomas908Author Commented:
That we are already doing.
But want to change to xml so that there is only one file.
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
expertmbCommented:
my SUGGESTIO. below xml structure is to maintain

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="window.xsl"?>

<doc>
      <english>
            <title>TITLE ENGLISH</title>
            <body>
                  <objKey1>EngVal1</objKey1>
                  <objKey2>EngVal2</objKey2>
                  <objKey3>EngVal3</objKey3>
                  <objKey4>EngVal4</objKey4>
            </body>
      </english>

      <french>
            <title>TITLE FRENCH</title>
            <body>
                  <objKey1>FrenchVal1</objKey1>
                  <objKey2>FrenchVal2</objKey2>
                  <objKey3>FrenchVal3</objKey3>
                  <objKey4>FrenchVal4</objKey4>
            </body>
      </french>
</doc>

0
 
expertmbCommented:
typo,
SUGGESTION
0
 
thomas908Author Commented:
what'll be the use of doing this ?
0
 
expertmbCommented:
easy to  manintain. reflects the properties files of different locales. i will post the code how to access the value for different locale related messages.
0
 
thomas908Author Commented:
PLease post the code.
thanks
0
 
objectsCommented:
how about having a seperate xsl for each locale
or first generate the xsl based on the local

have you tried asking in the xml ta?
0
 
thomas908Author Commented:
>>have you tried asking in the xml ta?

No haven't.
I'll give it a try
0
 
expertmbCommented:
XML

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="window.xsl"?>

<doc>
      <language >
            <lang type="english">
                  <title>TITLE ENGLISH</title>
                  <body>
                        <objKey1>EngVal1</objKey1>
                        <objKey2>EngVal2</objKey2>
                        <objKey3>EngVal3</objKey3>
                        <objKey4>EngVal4</objKey4>
                  </body>
            </lang>
      </language>

      <language>
            <lang type="french">
                  <title>TITLE FRENCH</title>
                  <body>
                        <objKey1>FrenchVal1</objKey1>
                        <objKey2>FrenchVal2</objKey2>
                        <objKey3>FrenchVal3</objKey3>
                        <objKey4>FrenchVal4</objKey4>
                  </body>
            </lang>
      </language>
</doc>
0
 
expertmbCommented:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import java.io.*;
import java.util.*;
import org.w3c.dom.Document;
import org.w3c.dom.DOMException;
import org.w3c.dom.Node;
import org.w3c.dom.*;


public class XMLParser {
      private static ArrayList list = null;
      private static Document document = null;

      public static Document getXMLDocument() throws Exception {
            if(document == null){
                  try{
                        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                        DocumentBuilder builder = factory.newDocumentBuilder();
                        String xmlFile = "d:\\RND\\myXML.xml";
                        document = builder.parse(new File(xmlFile));
                  }catch (Exception e) {
                        throw new Exception("Error occurred while loading the XML file."
                        + e.getMessage());
                  }
            }

            return       document;
      }

      public static ArrayList getAttributesOfElementNode(Node cNode, String Name) {
            String attrValue = null;
            try {
                  if(cNode.getNodeType() == Node.ELEMENT_NODE)
                  {
                        if( Name.equals(cNode.getNodeName()) )
                        {
                              NamedNodeMap attributeMap = cNode.getAttributes();
                              ArrayList tempList = new ArrayList(1);
                              int length = attributeMap.getLength();
                              for (int i=0; i<length; i++)
                              {
                                    Attr attribute = (Attr)attributeMap.item(i);
                                    attrValue = attribute.getNodeValue();
                                    tempList.add(attrValue);
                              }
                              list.add(tempList);
                        }
                        NodeList nList = cNode.getChildNodes();
                        int length1 = nList.getLength();
                        if(length1 != 0)
                        {
                              for (int i=0; i<length1; i++)
                                    getAttributesOfElementNode(nList.item(i), Name);
                        }
                  }
            }catch(Exception e) {
                  e.printStackTrace();
            }
            return list;
      }

      public static ArrayList getNodeDataValue(Node cNode, String name){
            String nodeValue = null;
            try
            {
                  if (cNode.getNodeType() != Node.TEXT_NODE){
                        NodeList nList = cNode.getChildNodes();
                        int length = nList.getLength();
                        if(length != 0)
                        {
                              int length1 = nList.getLength();
                              for (int i=0; i<length1; i++)
                              {
                                    Node tempNode =  nList.item(i);
                                    if( tempNode.getNodeType() == Node.TEXT_NODE ) {
                                          if ( name.equals(cNode.getNodeName()) && !
                                                tempNode.getNodeValue().trim().equals("")) {
                                                nodeValue = tempNode.getNodeValue();
                                                list.add(nodeValue);
                                          }
                                    } else
                                          getNodeDataValue(tempNode, name);
                              }
                        }
                  }
            }catch(Exception e) {
                  e.printStackTrace();
            }
            return list;
      }

      private static String getAttribute(NamedNodeMap nodeMap, String name) {
            Node node;
            String attrname;
            String attrval=null;
            if (nodeMap != null) {
                  int length = nodeMap.getLength();
                  for (int i=0; i<length; i++) {
                        node = nodeMap.item(i);
                        attrname = node.getNodeName();
                        if(name.equals(attrname))
                              attrval  = node.getNodeValue();
                  }
            }
            return attrval;
      }


      public static void setList(ArrayList list1){
            list = list1;
      }


      public String getValue(String language, String key) throws Exception{
            try{
                  String suffix = null;
                  NodeList nodelist = document.getElementsByTagName("lang");

                  int length = nodelist.getLength();
                  for (int j=0; j < length; j++) {
                        Element element = (Element)nodelist.item(j);
                           NamedNodeMap nodeMap = element.getAttributes();
                        String type = getAttribute(nodeMap,"type");
                        String langType = language;
                        if(langType.equals(type)) {
                              XMLParser.setList(new ArrayList());
                              suffix = (String)XMLParser.getNodeDataValue(element,
                                                key).get(0);
                        }
                  }

                  return suffix;
            }catch(Exception ex){
                  throw new Exception("Failed to get value for key " +
                  key      + "for langauge "            +      ex.getMessage());
            }
      }

      public static void main(String [] s){

            try{
                  getXMLDocument();
                  XMLParser parser = new XMLParser();
                  String str = parser.getValue("french", "objKey1");
                  System.out.println(str);
            }      catch(Exception ex){
                  System.out.println(ex);
            }
      }
}
0
 
thomas908Author Commented:
I am sorry expertmb.
i am told now a similar xml needs to be used as initally posted by me and not to use the structure as suggessted by u. And i need to use SAX for parsing.
i appreciate your effort.
thanks
0
 
Giant2Commented:
0
 
thomas908Author Commented:
What I am trying to do is, if attribute is "en_US" it should be added to 1 ArrayList and if its "fr_FR" it should be added to another arraylist.

tried doing the follwowing

  public void startElement(String namespaceURI, String localName,
                           String fullName, Attributes attributes) {
    if(locale.toString().equals("en_US")) {
      if (attributes.getValue(0).equals("en_US")) {
       enArrayList.add(str);

      }
    }
   for(int i=0; i<enArrayList.size(); i++) {
      System.out.println("array:  "+enArrayList.get(i));
    }

  }

  public void endElement(String namespaceURI, String localName,
                         String fullName) {

  }

  public void characters(char[] chars, int start, int end) {
      str = new String(chars, start, end);
  }
}

But the problem is bcoz startElement() gets executed before characters, I get a NullPointerException if I try to use str in startElement. how can i get around this?
0
 
Giant2Commented:
You posted an XML with some data.
And an XSL that try to structure these data of XML in a table manner (many table containing as row the values 2/3/...)
Now you say:
>What I am trying to do is, if attribute is "en_US" it should be added to 1 ArrayList and if its "fr_FR" it should be added to another arraylist.

ArrayList are part of Java code, not XML/XSL. What exactly you want to do?
Read the XML using the XSL? But on this you do not have en_US attribute because are changed and organized by the XSL.
Tell me more, please.
0
 
thomas908Author Commented:
There is a java file which displays some content in JEditorPane().
The content which is displayed comes from an XML file. XSL is used to display the data in table format.
Now the question is which data to display in the JEditorpane ?
The answer to this is , this depands on the locale.
 If the locale is "en_US" then the data within those elements which have attributes "en_US" will be displayed.
 If the locale is "fr_FR" then data within those elements which have attributes "fr_FR" will be displayed.
I am trying to parse the XML file using SAX so that I can add all the elements to an
ArrayList depending on what attributes they have(if attribute is "en_US" they are added to 1 ArrayList and if attribute is "fr_FR" they are added to another "ArrayList"). The problem here is how to display values in table format , even after they come in an ArrayList(Although first problem is to get them in teh arraylist).

Earlier the approach I was thinking was to use a XSL to display the data. But the problem here is how to get the users locale in teh xsl.
i dont know which is the right way and if there is some other way .
If i am still not clear, please let me know. I'll try to explain again.
thanks
0
 
Giant2Commented:
Using the Locale in the XML/XSL I search, but find none. So I believe there is no possibility to have the Locale in this.
The thing you can do is to parse directly in 2 manner. I explain it.
Before parsing the XML with an XSL you could test in your java code what locale is.
So you have prepared 2 XSLT file that transform the XML in 2 differnet manner.
The first take only the en_US values; the second take only the fr_FR values.
At this moment you could parse the XML using first(US) or second(FR) XSLT because in the java code you know what locale is. So, now you could have what I suppose you want [a version of the XML/XSL in the locale language].
This is an idea.
Hope this could help you.
Bye, Giant.
0
 
objectsCommented:
> So you have prepared 2 XSLT file that transform the XML in 2 differnet manner.

I mentioned a similiar approach above

> The first take only the en_US values; the second take only the fr_FR values.
> At this moment you could parse the XML using first(US) or second(FR) XSLT because in the java code you know what locale is.

You shouldn't need to parse the xml at all, as the xsl could just use the relevant values for the target locale.
0
 
Giant2Commented:
look at "parse" like an "apply XSLT to XML".
:)
0
 
thomas908Author Commented:
>>If you need I will  send an example
please send an example
0
 
ramazanyichCommented:
Your stylesheet should be:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:param name="lang"/>
 <xsl:template match="/">
  <html>
  <body>
   <h2><xsl:value-of select="doc/title/string[@lang=$lang]"/></h2>

   <table border="1">
      <xsl:for-each select="doc/body/val">
      <tr>
              <td><xsl:value-of select="string[@lang=$lang]"/></td>
      </tr>
     </xsl:for-each>
   </table>

  </body>
  </html>
 </xsl:template>
</xsl:stylesheet>

In your java code add following Line before calling transform():
xformer.setParameter("lang", Language.getLocale().getLanguage());


0
 
thomas908Author Commented:
thanks. it doesn't print anyhting.

here's the xsl file
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:param name="lang"/>
 <xsl:template match="/">
  <html>
  <body>
   <h2><xsl:value-of select="doc/title/string[@lang=$lang]"/></h2>

   <table border="1">
      <xsl:for-each select="doc/body/val">
      <tr>
              <td><xsl:value-of select="string[@lang=$lang]"/></td>
      </tr>
     </xsl:for-each>
   </table>

  </body>
  </html>
 </xsl:template>
</xsl:stylesheet>

and the xml file

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="window.xsl"?>

    <doc>
     <title>
       <string lang="en_US">1</string>
       <string lang="fr_FR">2</string>
     </title>
     <body>
       <val>
          <string lang="en_US">3</string>
          <string lang="fr_FR">4</string>
       </val>
       <val>
          <string lang="en_US">5</string>
          <string lang="fr_FR">6</string>
       </val>
    </body>
    </doc>
0
 
CEHJCommented:
What you need is a Map of Template, keyed on Locale
0
 
thomas908Author Commented:
plz elaborate
0
 
ramazanyichCommented:
In my example I used:
xformer.setParameter("lang", Language.getLocale().getLanguage());
 Language.getLocale().getLanguage() returns language part of Locale: en or fr in your case:
So you need to use:
xformer.setParameter("lang", Language.getLocale().getLanguage()+"_"+ Language.getLocale().getLanguage().toUpperCase());

0
 
thomas908Author Commented:
tried this xsl
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="/">
 <xsl:param name="lang"/>
  <html>
  <body>

   <h2><xsl:value-of select="doc/title"/></h2>
   <h2><xsl:value-of select="doc/title/string[@lang=$lang]"/></h2>
   <table border="1">
      <xsl:for-each select="doc/body/val">
      <tr>
           <xsl:for-each select="string">
              <td><xsl:value-of select="."/></td>
          </xsl:for-each>
      </tr>
     </xsl:for-each>
   </table>

  </body>
  </html>
 </xsl:template>
</xsl:stylesheet>

with this java code xformer.setParameter("lang", Language.getLocale().getLanguage()+"_"+ Language.getLocale().getLanguage().toUpperCase());

It displays everything apart from teh parameter.
0
 
ramazanyichCommented:
There is an error in your xsl file
<xsl:param name="lang"/>
must be before <xsl:template> element
0
 
thomas908Author Commented:
tried changing attributes in xml file to "en" and "fr" as well along with
xformer.setParameter("lang", Language.getLocale().getLanguage());

still does not work
0
 
ramazanyichCommented:
On my PC I tried following example:
XSL file:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:param name="lang"/>
 <xsl:template match="/">
  <html>
  <body>
   <h2><xsl:value-of select="doc/title/string[@lang=$lang]"/></h2>

   <table border="1">
      <xsl:for-each select="doc/body/val">
      <tr>
              <td><xsl:value-of select="string[@lang=$lang]"/></td>
      </tr>
     </xsl:for-each>
   </table>

  </body>
  </html>
 </xsl:template>
</xsl:stylesheet>

XML file:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="window.xsl"?>

    <doc>
     <title>
       <string lang="en_US">1</string>
       <string lang="fr_FR">2</string>
       <string lang="ru_RU">3</string>
     </title>
     <body>
       <val>
          <string lang="en_US">3</string>
          <string lang="fr_FR">4</string>
       <string lang="ru_RU">5</string>
       </val>
       <val>
          <string lang="en_US">5</string>
          <string lang="fr_FR">6</string>
       <string lang="ru_RU">7</string>
       </val>
    </body>
    </doc>

Java source(simple test.java which uses only transform part of your code):
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.sax.*;
import javax.xml.transform.stream.*;
import java.util.*;
import java.io.*;

public class test{

public static void main(String[] args) throws Exception{

TransformerFactory factory = TransformerFactory.newInstance();

      Templates template = factory.newTemplates(new StreamSource(
          new FileInputStream(args[0])));

      Transformer xformer = template.newTransformer();

      Source source = new StreamSource(new FileInputStream(args[1]));
   // gives Locale
      Locale locale=Locale.getDefault();
      System.out.println("Locale: "+locale);

      // Apply the xsl file to the source file and write the result to the output file
      StreamResult result = new StreamResult(new StringWriter());
      xformer.setParameter("lang", locale.getLanguage()+"_"+ locale.getLanguage().toUpperCase());

      xformer.transform(source, result);
      StringWriter writer = (StringWriter) result.getWriter();
      System.out.println( (writer.getBuffer()).toString());
}
}

I executed it:
java test 555.xsl 555.xml

output was:
<html>
<body>
<h2>3</h2>
<table border="1">
<tr>
<td>5</td>
</tr>
<tr>
<td>7</td>
</tr>
</table>
</body>
</html>

As it is expected, because my default Locale is russian.

0
 
CEHJCommented:
You could try something like this


TemplateMap localeTemplates = new TemplateMap();
Templates ourTemplates = localeTemplates.getTemplates(Locale.getDefault());

.................


public class TemplateMap {
      private HashMap localesToTemplates;
      private TransformerFactory factory;
      
      public TemplateMap() {
            localesToTemplates = new HashMap();
            factory = TransformerFactory.newInstance();
      }
      
      public void addMappings() {
            // This should be done from a config file but ...
            localesToTemplates.add(new Locale(Locale.FRENCH), new LocaleSource("fr.xsl"));
            
      }

      class LocaleSource implements javax.xml.transform.Source {
            private String systemId;
            
            public LocaleSource(String systemId) {
                  this.systemId = systemId;
            }
            
            public void setSystemId(String systemId) {
                  this.systemId = systemId;
            }
            
            public String getSystemId() {
                  // return the system id set
            }


      }
      
      public Templates getTemplates(Locale locale) {
            return factory.newTemplates((Source)localesToTemplates.get(locale));
      }
}
0
 
thomas908Author Commented:
thanks you so much for helping.
0
 
CEHJCommented:
8-)
0
 
objectsCommented:
> What you need is a Map of Template, keyed on Locale

what I already suggested ;)
0
 
CEHJCommented:
Where?
0
 
objectsCommented:
Sorry but its your responsibility to read previous comments before posting :)
0
 
CEHJCommented:
Well i too am sorry - i've done a string search of 'map' on this page and it certainly doesn't come up in any of your comments
0
 
objectsCommented:
Well thats conclusive then, ROTFL
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.