PaulL Posted April 8, 2009 Report Share Posted April 8, 2009 The solution to this may go beyond LabVIEW, but I expect this will be of general interest to many LabVIEW developers in any case. Background: 1) As of LabVIEW 8.6 the "Flatten To XML" and "Unflatten From XML" functions support LabVIEW objects. We can use the "Flatten To XML" function to serialize LabVIEW objects to strings, send the strings over a network using, for example, a string shared variable, and then recast to the original object on the receiving computer using the "Unflatten From XML" function. (Note that the class definitions must be available to both the sending and receiving application, but this is not difficult.) 2) There are various methods to send string messages between Java and LabVIEW applications. 3) XML is well-suited to sharing data between development environments. Problem: We have a LabVIEW object in our LabVIEW application. We use "Flatten To XML" to serialize the object to XML and send the resulting XML string to Java. Now we want to convert the XML string to a Java class. What is the best way to do this? (Of course we next will want to go the other way.) Considerations: I kind of understand the key words (DOM, Xerces) but I don't know quite enough about XML in Java to know which direction to take. I do know that we will have to translate LabVIEW types into Java types. Does anyone have experience with XML and would be able to point us in a good direction? Quote Link to comment
alexwarrior Posted April 11, 2009 Report Share Posted April 11, 2009 Hi Paul, Probably the way I'd do it is through an XSL transformation. That's a good way of translating between different XML applications; you write an XSLT file, pass it along with the XML input file, and the XSLT processor outputs the translated XML file. You'll need to create an XSL stylesheet, and then pass it through an XSLT processor. LabVIEW can't do the transformation though, so you'll need to use an external one. I remember using command line tools that do it, that just take the two input files as arguments and the output file is produced. Or you can do it programitcally, although I haven't done it in Java, just .NET languages. In .NET, it just takes a few lines of code (three or so?), and I'm guessing with a Java base processor (Xalan-java perhaps?) it's just as easy. A beginner might be tempted to do the transformation by manually traversing a DOM and picking out elements with lots of if..then...else... but this can be tedious and error-prone. Hope this helps! - Alex Quote Link to comment
PaulL Posted April 11, 2009 Author Report Share Posted April 11, 2009 Alex, I looked at a few web pages on XSLT and this solution looks quite promising (and is an incarnation of what I was looking for). We'll have to investigate further and see if works for us. Thanks much! Paul Quote Link to comment
Aristos Queue Posted April 11, 2009 Report Share Posted April 11, 2009 Paul: I suspect you will -- believe it or not -- NOT want to use the Flatten to XML primitive for the LV Objects directly. Rather, I suspect you want to add a member VI to the class that outputs a custom XML format of the data within the class. Why? Because you're using it to move from one platform to another. The XML format of objects is designed to be mutation and version aware in LabVIEW. There are many shortcuts that the format takes that are not comprehensible without the .lvclass file. For example, if the output XML is just the class name followed by a version number of 0.0.0.0, that means unflatten this as the default value of the class. But without the .lvclass file, how can you know the default value at all? Any time you're going to be leaving LabVIEW, the standard format of XML for objects is not going to be useful. Instead, build a cluster of the data that you want in the XML and then flatten that cluster as XML. That will give you a format that is completely LV independent to read in your JAVA code. -- AQ Quote Link to comment
PaulL Posted April 15, 2009 Author Report Share Posted April 15, 2009 AQ, OK. Well, thanks for the heads-up. I thought the Java code could just ignore the version numbers but if (and I just ran a test to see this in action) LabVIEW doesn't put any values in the XML if they are default for the object (maybe I'm not stating this exactly correctly) that definitely is a problem for handing over to Java. Thanks for the heads-up. Creating a cluster manually (by which I mean the cluster definition is determined before compiling), of course, possible, but I think it kind of defeats the purpose and it will be quite difficult to set up the hierarchy correctly. So I will see if I can generate a cluster (based on the object data) programmatically (by iteratively traversing the hierarchy). I think this will be possible but I suspect there are a couple aspects of this that are nontrivial.... Paul Quote Link to comment
Aristos Queue Posted April 15, 2009 Report Share Posted April 15, 2009 QUOTE (Paul_at_Lowell @ Apr 13 2009, 05:55 PM) Creating a cluster manually (by which I mean the cluster definition is determined before compiling), of course, possible, but I think it kind of defeats the purpose and it will be quite difficult to set up the hierarchy correctly. It doesn't defeat the purpose. The XML form of an object is meant for preserving the object as the object. If you want to change it to a different object -- and that includes changing to a different object in a different language -- you would go through some sort of stabilized, exported interface, such as creating a non-object structure (aka cluster) and serializing the information. That's pretty much standard procedure for any sort of export/import operation. That leaves you free to still change the private details of your object -- add fields, remove fields, etc -- without changing your import/export format and thereby creating incompatibilities with the importing system. Quote Link to comment
Mark Smith Posted April 15, 2009 Report Share Posted April 15, 2009 QUOTE (Aristos Queue @ Apr 13 2009, 11:24 PM) It doesn't defeat the purpose. The XML form of an object is meant for preserving the object as the object. If you want to change it to a different object -- and that includes changing to a different object in a different language -- you would go through some sort of stabilized, exported interface, such as creating a non-object structure (aka cluster) and serializing the information. That's pretty much standard procedure for any sort of export/import operation. That leaves you free to still change the private details of your object -- add fields, remove fields, etc -- without changing your import/export format and thereby creating incompatibilities with the importing system. You might want to have a look at the XML-RPC protocol for serialization of data to export from LabVIEW and import into Java. Compared to any other XML protocol (like SOAP) I've explored, it's very simple yet very flexible. The XML-RPC Server project in the CR has tools to pack LabVIEW data types (the ones XML-RPC supports) into XML-RPC compliant XML and then into an XML-RPC method call and Java has several implementations to choose from (http://www.xmlrpc.com/directory/1568/implementations) to unpack the data and execute the requested method. Here, your method call just sends data to the Java client (the Java client could just read the serialized call from disk if you choose to write it there) and the client side method unpacks the data fields and builds a new object from that. The advantage here is that you can use existing tools to serialize the data for transport from LabVIEW to Java and you won't have to roll your own - instead, you can concentrate on how to get the object data to build the XML-RPC call from LabVIEW and the Java code to re-build that object as the method. Mark Quote Link to comment
PaulL Posted April 15, 2009 Author Report Share Posted April 15, 2009 Mark, Thanks for the hint! I am looking at the XML-RPC information now and will see if that suits our needs. Everyone, For the record, here is a link to the CR page: XML-RPC Server for LabVIEW and a discussion thread XML-RPC Implementation in LabVIEW. Paul Quote Link to comment
PaulL Posted April 15, 2009 Author Report Share Posted April 15, 2009 OK, so I spent some time talking with our Java developer after trying a couple things, and here is what I am thinking (which could be wrong!): 1) We are not seeking a the transport mechanism. We already have a transport mechanism to send and receive data (in this case strings that will be XML strings). We are only interested in writing data to and reading data from XML. 2) Our XML strings are all strictly data. They are not fundamentally procedure calls (although in practice the distinction may be mostly philosophical--I'm not sure about that). 3) The basic format we need is element name with a nested element with the value. So JKI's EasyXML tool is a good example of what will work for us. In fact, I would stop here if that excellent tool supported LabVIEW objects (but it doesn't yet). 4) So that leaves us with the task of writing a framework to traverse the object data. Now each class, of course, has a control (in a .ctl file) associated with it, and that control is always a cluster. I can cast that control to a cluster and use EasyXML to turn it into XML, with a notable difficulty. (See the next item.) 5) OK, I have to handle the case in which the object itself contains other objects. In that case I have to determine if a contained element is a LabVIEW object or not. If it is, I have to determine the object type and then get the appropriate class's .ctl file (I haven't quite worked this out here), keeping in mind that it could be an abstract class. 6) The class .ctls ought to provide the appropriate clusters (barring the question of how to handle sub-objects again) that we should use to hand to the XML. I think it should be possible to write a framework to traverse the object data without writing code within each class to generate XML specifically for that class. (This is along the lines of some of the frameworks available in the Java world.) So I think the problem in step 5 will make or break us. I'm going to see what I can do! (OK, I've only concentrated in getting data from LabVIEW to Java. I still have to be sure we can do the opposite.) Paul Quote Link to comment
PaulL Posted April 16, 2009 Author Report Share Posted April 16, 2009 I am attaching an image of the code to illustrate what I am trying. Executing the code results in the following XML output [just for the relatively uninteresting TCSState object, which is just one component of TCSPublicStatus, and which has only one member, tcsState (an ENUM)]: <TCSState.lvclass> <tcsState>READY</tcsState> </TCSState.lvclass> Unfortunately this isn't quite general, since I don't have a reliable way to get the current object data and put it into the cluster. Maybe there is a way to do this? If so, then I have to add code to check if a given element is a LabVIEW object or not, as I said. I just wanted to see if I could create meaningful XML data for an object at all. (The answer is right now a very qualified yes.) Paul Quote Link to comment
PaulL Posted April 16, 2009 Author Report Share Posted April 16, 2009 OK, I replaced the center section with code that automatically updates the cluster elements before writing to XML. (Sorry for the wide picture. I purposely kept all the code at the top level so that reviewers could see the whole picture.) To do this I made the assumption that the accessor methods are automatically generated by LabVIEW, which is not necessarily true. I'm hoping there is a better way. The good news is that this method does what I intended it to do. The next thing is to determine if a cluster element is a LabVIEW object or not.... Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.