Solved

Xml to Java Using Xstream (attribute issue)

Posted on 2010-09-23
24
813 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
 
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
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 

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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

The Client Need Led Us to RSS I recently had an investment company ask me how they might notify their constituents about their newsworthy publications.  Probably you would think "Facebook" or "Twitter" but this is an interesting client.  Their cons…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Viewers learn about the “for” loop and how it works in Java. By comparing it to the while loop learned before, viewers can make the transition easily. You will learn about the formatting of the for loop as we write a program that prints even numbers…
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.

708 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now