Solved

Xml to Java Using Xstream (attribute issue)

Posted on 2010-09-23
24
832 Views
Last Modified: 2012-05-10
Hi,

I'm using Xstream 1.2.1 and I'm trying to convert this XML

<Name id="1">John</Name>

Into a Java Object.

Here's the "Name" class and my code.

The result is :
1
null
public class Name{
		private String id ="";
		private String value = "";
		public String getId() {
			return id;
		}
		public void setId(String pId) {
			id = pId;
		}
		public String getValue() {
			return value;
		}
		public void setValue(String pValue) {
			value = pValue;
		}
	}

Open in new window

XStream xstream = new XStream();
		xstream.alias("Name", Name.class);
		xstream.useAttributeFor("id", String.class);
		String fluxXml = "<Name id=\"1\">John</Name>";
		Name name = (Name)xstream.fromXML(fluxXml);
		System.out.println(name.getId());
		System.out.println(name.getValue());

Open in new window

0
Comment
Question by:jaypi
  • 14
  • 10
24 Comments
 
LVL 16

Expert Comment

by:Valeri
ID: 33745752
0
 

Author Comment

by:jaypi
ID: 33745786
It's not the same. In the link you sent, the solution describes how to convert from an Object to XML :

System.out.println(xStreamObj.toXML(g));

I need to do the opposite.

Mapping :

<Name id="1">John</Name>

to an Object
0
 
LVL 16

Expert Comment

by:Valeri
ID: 33745969
try with
xstream.aliasField("Name", Name.class, "value");
instead of
String fluxXml = "<Name id=\"1\">John</Name>";
0
Webinar: Aligning, Automating, Winning

Join Dan Russo, Senior Manager of Operations Intelligence, for an in-depth discussion on how Dealertrack, leading provider of integrated digital solutions for the automotive industry, transformed their DevOps processes to increase collaboration and move with greater velocity.

 
LVL 16

Expert Comment

by:Valeri
ID: 33745992
I mean before :-)
String fluxXml = "<Name id=\"1\">John</Name>";
0
 

Author Comment

by:jaypi
ID: 33746072
Doesn't work:

System.out.println(name.getId());
System.out.println(name.getValue());

1
null
0
 
LVL 16

Expert Comment

by:Valeri
ID: 33746305
wow?!
I think that in your class 'value' must be replaced with 'name'
public class Name{
            private String id ="";
            private String name = "";
            public String getId() {
                  return id;
            }
            public void setId(String pId) {
                  id = pId;
            }
            public String getName() {
                  return name;
            }
            public void setName(String pName) {
                  name = pName;
            }
      }
0
 

Author Comment

by:jaypi
ID: 33746402
Not good

Here's a recap :

      public class Name{
            private String id ="";
            private String name = "";
            public String getId() {
                  return id;
            }
            public void setId(String pId) {
                  id = pId;
            }
            public String getName() {
                  return name;
            }
            public void setName(String pName) {
                  name = pName;
            }

            XStream xstream = new XStream();
            xstream.alias("Name", Name.class);
            xstream.useAttributeFor("id", String.class);
            xstream.aliasField("name", Name.class, "value");
            String fluxXml = "<Name id=\"1\">John</Name>";
            Name name = (Name)xstream.fromXML(fluxXml);
            System.out.println(name.getId());
            System.out.println(name.getName());
            System.out.println(xstream.toXML(name));

Output :
1
null
<Name id="1"/>
0
 
LVL 16

Expert Comment

by:Valeri
ID: 33747400
Actually I was wrong, because you can't proceed in this way.
<Name id="1">John</Name> is not valid xml.
I think that in order to parse it with the original class from your question it should be something like that:
<Name id="1">
   <value>John</value>
</Name>
0
 

Author Comment

by:jaypi
ID: 33747572
You are wrong, this XML is perfectly valid.

Check it here: http://www.w3schools.com/XML/xml_validator.asp
0
 
LVL 16

Expert Comment

by:Valeri
ID: 33748610
tag Name is mapped to Name.class, attribute id is mapped to member id, but to member name nothing is mapped... that's way you need tag in order to have this mapping too. This works :
import com.thoughtworks.xstream.XStream;

public class Name {
    private String id = "";
    private String name = "";

    public Name(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
          return id;
    }
    public void setId(String pId) {
          id = pId;
    }
    public String getName() {
          return name;
    }
    public void setName(String name) {
          this.name = name;
    }
    public static void main(String[] args) {
        XStream xstream = new XStream();
        xstream.alias("Name", Name.class);
        xstream.useAttributeFor("id", String.class);
        String fluxXml = "<Name id=\"5\"><name>John</name></Name>";
        Name name = (Name)xstream.fromXML(fluxXml);
        System.out.println(name.getId());
        System.out.println(name.getName());

        Name name2 = new Name("7", "Peter");
        System.out.println(xstream.toXML(name2));
    }
}
0
 

Author Comment

by:jaypi
ID: 33748662
I can't decide on the format of the XML, so I can't use that:

<Name id="5"><name>John</name></Name>

I need to know if there's a way mapping this:

<Name id="5">John</Name>
0
 
LVL 16

Expert Comment

by:Valeri
ID: 33748729
This is because this is a library for serialization from xml to objects and from objects to xml, and each tag from xml must correspond to the respective member of the class...
0
 

Author Comment

by:jaypi
ID: 33748762
I can't believe that Xstream can't take such a basic XML... :(
0
 
LVL 16

Expert Comment

by:Valeri
ID: 33748913
It can, but you need more code to do that... I'll try to send you this code...
0
 
LVL 16

Expert Comment

by:Valeri
ID: 33749316
You have to use single tag convertors. See the attached files.
Name.java
NameConverter.java
0
 

Author Comment

by:jaypi
ID: 33749347
Thanks for this code, but the example is really an easy case:

In reality, the xml to convert is much more bigger:

<request>
<name id="1">John</name>
<adress>
<street number="21">Street name</street>
<city zip="123">Gotham City</city>
</adress>
...
</request>

It's a bit tedious to create a converter for each tag...
0
 
LVL 16

Expert Comment

by:Valeri
ID: 33751796
There is no way to avoid the converter in this case. The only way to avoid converter is to use the following format:
<Name id="5">
<name>John</name></Name>
0
 
LVL 16

Expert Comment

by:Valeri
ID: 33751832
...but you told me that you can't change the format of the xml, so you have to use the converter. Take a look at interface HierarchicalStreamReader, there is getValue() method and in your case this is the only way to set this value to the member "value" from your class. There is no other way for mapping.
If you don't want to write converters, then yuou have to ask the producer of the xml to change the xml like that:
<Name>
  <id>5</id>
  <value>John</value>
</Name>
0
 

Author Comment

by:jaypi
ID: 33751849
Thanks for your update Valeri.

I'm going to try another solution: transforming the xml with xsl

Input:
<test id="1">bla</test>

output:
<test>
 <id>1</id>
 <test>bla</test>
</test>

Don't see other solutions... Writing 15 converters... Not funny :D
0
 
LVL 16

Expert Comment

by:Valeri
ID: 33751914
Yes, may be it's the best solution in your case!
Other solution is to parse this XML by yourself withg SAX let say, and to produce the objects as you want.
Good luck!
0
 

Author Comment

by:jaypi
ID: 33751928
Here's the XSL to create an Xstream friendly XML:

Thanks to Gertone for that.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:template match="*[string-length(normalize-space(text())) > 0][@*]">
        <xsl:copy>
            <xsl:for-each select="@*">
                <xsl:element name="{name()}">
                    <xsl:value-of select="."/>
                </xsl:element>
            </xsl:for-each>
            <xsl:element name="{name()}">
                <xsl:apply-templates select="node()"/>
            </xsl:element>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="node()">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Open in new window

0
 
LVL 16

Expert Comment

by:Valeri
ID: 33752012
Looks good! I've never been so good in XSL transformations! :-)
If you don't need to transfer your objects back to the same xml later, I think that this is a good solution for you.
0
 
LVL 16

Accepted Solution

by:
Valeri earned 500 total points
ID: 33763311
Hi jaypi,
I've been thinking about your issue, you can write only one converter that converts a lot of tags like that:
<Name id="5">John</Name>
See the attached file. With one converter you can convert different types of tag.
I think that this is the best solution for you.
TagConverter.java
0
 

Author Comment

by:jaypi
ID: 33764211
Hi Valeri,

you finally found the best solution. Well done!
0

Featured Post

Space-Age Communications Transitions to DevOps

ViaSat, a global provider of satellite and wireless communications, securely connects businesses, governments, and organizations to the Internet. Learn how ViaSat’s Network Solutions Engineer, drove the transition from a traditional network support to a DevOps-centric model.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
XML SQL 8 27
SequenceInputStream example 3 19
how to debug htl and js pages 8 39
Need Help! Getting a syntax error and don't understand why 3 31
Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:

856 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question