Hi,

I was wondering if anybody has experienced a similar problem.  I am
trying to convert from a SOAPElement to a String, but i seem to be
getting empty strings when i use the getLocalName(), getURI(), etc
functions in javax.xml.soap.Name.  

Right now, if i try to do the conversion from SOAPElement to String
(attached SOAPUtil.convertSOAPElementToString), the attached XML file
comes out looking like this:

< ="rep1" ="rep1" ="rep1"><></>< ="e0"><></><><></></><></><
="Peter"></><></>< ="System"></><></></><></><
="e1"><></><><></></><></><><></></><></></><></>< =
"e2"><></><><></></><></><><></></><></><><></></><></></><></><
="e3"><></><><>
</></><></><><></></><></><><></></><></><><></></><></><><></></><></></><></><
="set1"><></><><></></><></><><></></><></><><></></><></><><></></><></></><><
/><
="User"><></><><></></><></><><></></><></><><></></><></><><></></><></></>
<></>< ="e1" ="e1" ="e1"></><></>< ="System" ="System"
="System"></><></>< ="Use r" ="User" ="User"></><></>< ="User" ="User"
="User"></><></>< ="set1" ="set1" = "set1"></><></>< ="set1" ="set1"
="set1"></><></>< ="e3" ="e3" ="e3"></><></></>

(in case anybody's mail reader is being boneheaded, basically, i get
attribute values and nothing else)

Would anybody know if the implementation for this interface is faulty in
any way?  Or is it the more likely case that i'm just not understanding
the API properly?

Cheers,

--eric

/* -*- Mode: java; indent-tabs-mode:nil; c-basic-offset: 2 -*-
 * ex: set sw=2 expandtab:
 * $Id:$
 *
 * This software is released under a BSD-style license.
 * Please see the LICENSE file in this distribution.
 */

package soapical.util;

import com.megginson.sax.XMLWriter;
import java.io.StringWriter;
import java.lang.IllegalArgumentException;
import java.util.Iterator;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import org.apache.log4j.Logger;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

/**
 * Miscellaneous utilities for converting between SOAP and other stuff
 *
 * @version
 * $Revision:$<br>
 * $Date:$<br>
 * @author Eric Kow (kow at loria point fr)
 */
public class SOAPUtil {
  static Logger _logger = Logger.getLogger(SOAPUtil.class);

  /**
   * I stole this from Sun at 
   * http://access1.sun.com/techarticles/SOAP_DOM/SOAP_DOM.html
   * thanks to their use of the BSD license (same as this one!)
   *
   * Standard recursion, folks, copying the tree, nothing to see.  Why i
   * didn't think to do this myself makes me feel like a very very very
   * dumb programmer
   */
  public static SOAPElement convertDOMToSOAPElement(SOAPEnvelope env, 
                                                    org.w3c.dom.Node DOMNode)
  throws SOAPException{ 

    //Test that DOMNode is of type org.w3c.dom.Node.ELEMENT_NODE. 
    if((DOMNode.getNodeType()) != org.w3c.dom.Node.ELEMENT_NODE) 
      throw new SOAPException("DOMNode must of type ELEMENT_NODE"); 


    SOAPFactory factory = SOAPFactory.newInstance(); 
    Name sn = factory.createName(DOMNode.getLocalName(), 
                                 DOMNode.getPrefix(), 
                                 DOMNode.getNamespaceURI()); 
    SOAPElement se = factory.createElement(sn);

    if (DOMNode.hasAttributes()){ 
      NamedNodeMap DOMAttributes = DOMNode.getAttributes(); 
      int noOfAttributes = DOMAttributes.getLength(); 
      for(int i = 0; i < noOfAttributes; i++){ 
        org.w3c.dom.Node attr = DOMAttributes.item(i); 
        se.addAttribute(env.createName(attr.getLocalName(), attr.getPrefix(), 
                                       attr.getNamespaceURI()), attr.getNodeValue()); 
      }
    }


    if(DOMNode.hasChildNodes()){ 
      NodeList children = DOMNode.getChildNodes(); 
      for(int i = 0; i< children.getLength(); i++){ 
        org.w3c.dom.Node child = children.item(i); 

        switch(child.getNodeType()){ 
          case org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE: break; 
          case org.w3c.dom.Node.DOCUMENT_TYPE_NODE: break; 
          case org.w3c.dom.Node.CDATA_SECTION_NODE:
          case org.w3c.dom.Node.COMMENT_NODE:
          case org.w3c.dom.Node.TEXT_NODE:
                                                    
se.addTextNode(child.getNodeValue()); 
                                                    break; 
          default:              
                                                    
se.addChildElement(convertDOMToSOAPElement(env, child)); 
        }

      }//end of for 
    }//end of if 

    return se; 
  }

  /**
   * Convert a SOAPElement to XML string
   */
  public static String convertSOAPElementToString(SOAPElement element) {
    StringWriter writer = new StringWriter();
    XMLWriter xmlWriter = new XMLWriter(writer);

    try {
      xmlWriter.startDocument();
      convertSOAPElementToString_helper(element, xmlWriter);
      xmlWriter.endDocument();
      return writer.toString();
    } catch (SAXException e) {
      // FIXME: i wonder if we should do something with this exception;
      // we're basically not expecting to catch it, and it really 
      // wouldn't make any sense to throw it since it wouldn't be the
      // users fault, but our own...
      _logger.error("problem converting SOAP to String: " + e);
      return null;
    } 
  }

  /**
   * Convert a SOAPElement to XML string.
   */
  private static void 
    convertSOAPElementToString_helper(SOAPElement element,
                                      XMLWriter handler)
    throws SAXException
  {
    // a null element is unlikely but theoretically possible
    if (element == null) { 
      return;
    }

    if (handler == null) {
      throw new IllegalArgumentException("null xml writer");
    }

    // get the attributes
    AttributesImpl attrs = new AttributesImpl();
    for (Iterator iter = element.getAllAttributes();
         iter.hasNext(); ) 
    {
      Name attrName = (Name)(iter.next());
      String attrValue = element.getAttributeValue(attrName);
      // FIXME: i don't know what to put down for attr type...
      // would this information be in the SOAPElement? would it matter?
      attrs.addAttribute(attrName.getURI(),
                         attrName.getLocalName(),
                         attrName.getQualifiedName(),
                         "",
                         attrValue);
    }

    // open the current node
    Name name = element.getElementName();
    String URI = name.getURI();
    String localName = name.getLocalName();
    String qName = name.getQualifiedName();
    _logger.debug(" u[" + URI + "] " +
                  " l[" + localName + "]" +
                  " q[" + qName + "]");
    handler.startElement(URI, localName, qName, attrs);

    // write the node's children
    for (Iterator iter = element.getChildElements();
         iter.hasNext(); ) 
    {
      SOAPElement child = (SOAPElement)(iter.next());
      convertSOAPElementToString_helper(child, handler);
    }
    
    // close off the current node
    handler.endElement(URI, localName, qName);
  }
}

package soapical.util;

import junit.framework.TestCase;
// JUnitDoclet begin import
import soapical.util.SOAPUtil;
import java.io.File;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPElement;
import org.xml.sax.InputSource;
import java.io.StringReader;
import org.apache.log4j.Logger;
// JUnitDoclet end import

/**
* Generated by JUnitDoclet, a tool provided by
* ObjectFab GmbH under LGPL.
* Please see www.junitdoclet.org, www.gnu.org
* and www.objectfab.de for informations about
* the tool, the licence and the authors.
*/


public class SOAPUtilTest
// JUnitDoclet begin extends_implements
extends TestCase
// JUnitDoclet end extends_implements
{
  // JUnitDoclet begin class
  static final File TEST_ROOT = new File("etc/testing");
  static Logger _logger = Logger.getLogger(SOAPUtilTest.class);
  soapical.util.SOAPUtil soaputil = null;

  // JUnitDoclet end class
  
  public SOAPUtilTest(String name) {
    // JUnitDoclet begin method SOAPUtilTest
    super(name);
    // JUnitDoclet end method SOAPUtilTest
  }
  
  public soapical.util.SOAPUtil createInstance() throws Exception {
    // JUnitDoclet begin method testcase.createInstance
    return new soapical.util.SOAPUtil();
    // JUnitDoclet end method testcase.createInstance
  }
  
  protected void setUp() throws Exception {
    // JUnitDoclet begin method testcase.setUp
    super.setUp();
    soaputil = createInstance();
    // JUnitDoclet end method testcase.setUp
  }
  
  protected void tearDown() throws Exception {
    // JUnitDoclet begin method testcase.tearDown
    soaputil = null;
    super.tearDown();
    // JUnitDoclet end method testcase.tearDown
  }
  
  public void testConvertDOMToSOAPElement() throws Exception {
    // JUnitDoclet begin method convertDOMToSOAPElement
    // JUnitDoclet end method convertDOMToSOAPElement
  }
  
  public void testConvertSOAPElementToString() throws Exception {
    // JUnitDoclet begin method convertSOAPElementToString
    // we do this test in a roundabout way: by reading in a test
    // document, converting it to SOAP, converting it back, and 
    // making sure that the resulting XML trees are the same.
    //
    // a fundamental flaw in this is that it only tests that
    // convertDOMtoSOAP (and SOAP back to DOM) give the same thing, 
    // not really that each individual function works

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
 
    // read in and parse some sample data... this gives us a
    // DOM tree
    File file = new File(TEST_ROOT, "sample_mmil.xml");

    Document parse = builder.parse(file);
    Element parseRoot = parse.getDocumentElement();
    assertTrue(parseRoot != null);

    MessageFactory msgFactory = MessageFactory.newInstance();

    // convert the DOM tree to SOAP 
    // ideally we would have a seperate function for reading a file
    // directly into a SOAP element 
    SOAPEnvelope soapEnvelope =
      msgFactory.createMessage().getSOAPPart().getEnvelope();
    SOAPElement soap = 
      SOAPUtil.convertDOMToSOAPElement( soapEnvelope, parseRoot );

    // convert the SOAP to a String (this is the part we want to test)
    String soapString = 
      SOAPUtil.convertSOAPElementToString( soap );
    _logger.info("SOAP -> String: " + soapString);
    assertTrue( "SOAPElement is non-null, nonempty",
                soapString.length() > 0 );

    // parse the string back to a DOM tree and compare this with the
    // original DOM tree
    Document parse2 = 
      builder.parse( new InputSource(new StringReader(soapString)) );
    assertTrue( "SOAPElement converted successfully to String",
                SOAPTestUtils.compareDOM(parse, parse2) );
    // JUnitDoclet end method convertSOAPElementToString
  }
  
  
  
  /**
  * JUnitDoclet moves marker to this method, if there is not match
  * for them in the regenerated code and if the marker is not empty.
  * This way, no test gets lost when regenerating after renaming.
  * Method testVault is supposed to be empty.
  */
  public void testVault() throws Exception {
    // JUnitDoclet begin method testcase.testVault
    // JUnitDoclet end method testcase.testVault
  }
  
  public static void main(String[] args) {
    // JUnitDoclet begin method testcase.main
    junit.textui.TestRunner.run(SOAPUtilTest.class);
    // JUnitDoclet end method testcase.main
  }
}
<?xml version="1.0" encoding="ISO-8859-1"?>

<mmilComponent xmlns="http://www.miamm.org/mmil"; 
    id="rep1" type="semRep">
  <event id="e0">
    <evtType>Speak</evtType>
    <speaker target="Peter"/>
    <addressee target="System"/>
  </event>
  <event id="e1">
    <evtType>Show</evtType>
    <mode>Imperative</mode>
  </event>
  <event id="e2">
    <mode>Indicative</mode>
    <tense>Preterit</tense>
    <evtType>Listen</evtType>
  </event>
  <event id="e3">
    <individuation>singular</individuation>
    <evtType>Period</evtType>
    <lex>Morning</lex>
    <refType>Demonstrative</refType>
    <refStatus>Pending</refStatus>
  </event>
  <participant id="set1">
    <individuation>set</individuation>
    <objectType>Tune</objectType>
    <refType>Definite</refType>
    <refStatus>Pending</refStatus>
  </participant>
  <participant id="User">
    <MMILId>pers6546754</MMILId>
    <objectType>User</objectType>
    <refType>1PPDeixis</refType>
    <refStatus>Pending</refStatus>
  </participant>
  <relation source="e1" target="e2" type="propContent"/>
  <relation source="System" target="e1" type="subject"/>
  <relation source="User" target="e1" type="toObject"/>
  <relation source="User" target="e2" type="subject"/>
  <relation source="set1" target="e1" type="object"/>
  <relation source="set1" target="e2" type="object"/>
  <relation source="e3" target="e2" type="tempCircumstance"/>
</mmilComponent>

Reply via email to