xmlbeam icon indicating copy to clipboard operation
xmlbeam copied to clipboard

ClassCastException when setting child projection on parent as document root

Open zhsc opened this issue 8 years ago • 1 comments

I'm seeing this error while trying to set a child projection onto a parent projection where the @XBWrite segment is the document root.

Here's a test case:


import static org.junit.Assert.assertEquals;

import org.junit.Test;
import org.xmlbeam.XBProjector;
import org.xmlbeam.XBProjector.Flags;
import org.xmlbeam.annotation.XBWrite;

public class TestSetChildUnderDocumentRoot {

	public interface Child {
		@XBWrite("ChildData")
		void setData(String data);
	}
	
	public interface ParentNoRootElement {

		@XBWrite("Child")
		void setChild(Child child);
	}
		
	@Test
	public void testSetChildOnParentAsDocumentRoot() {
		XBProjector projector = new XBProjector(Flags.TO_STRING_RENDERS_XML);
		
		ParentNoRootElement parent = projector.projectEmptyDocument(ParentNoRootElement.class);
		
		Child child = projector.projectEmptyDocument(Child.class);
		child.setData("child data...");
		
		parent.setChild(child);  
		
		/* Throws:
		java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.DocumentImpl cannot be cast to org.w3c.dom.Element
			at org.xmlbeam.util.intern.DOMHelper.replaceElement(DOMHelper.java:511)
			at org.xmlbeam.ProjectionInvocationHandler$WriteInvocationHandler.invokeProjection(ProjectionInvocationHandler.java:669)
			at org.xmlbeam.ProjectionInvocationHandler$ProjectionMethodInvocationHandler.invoke(ProjectionInvocationHandler.java:206)
			at org.xmlbeam.ProjectionInvocationHandler.invoke(ProjectionInvocationHandler.java:879)
			at com.sun.proxy.$Proxy5.setChild(Unknown Source)
		 */
		
		System.out.println("Result: " + parent);
		
		assertEquals(
				  "<Child>\n"
				+ "   <ChildData>child data...</ChildData>\n"
				+ "</Child>",
				parent.toString());
	}
}

zhsc avatar Apr 12 '18 23:04 zhsc

Ah... this is not possible right now, but I can give you an workaround:

public interface Child {
    @XBWrite("ChildData")
    void setData(String data);
}

public interface ParentNoRootElement {

    @XBWrite("/*")
    void setChild(Child child);
}
    
@Test
public void testSetChildOnParentAsDocumentRoot() {
    XBProjector projector = new XBProjector(Flags.TO_STRING_RENDERS_XML);
    
    ParentNoRootElement parent = projector.projectEmptyDocument(ParentNoRootElement.class);
    
    Child child = projector.projectEmptyElement("Child",Child.class);
    child.setData("child data...");
    parent.setChild(child);  
    System.out.println("Result: " + parent);
}
  1. Writing to the root nonexisting element is possible, but you need to use "/*" as XPath expression.
  2. Your Child instance was a document, which has no name for the element. You need to create an Element instead of Document as child.

I will try to make root element replacements easier in the future.

SvenEwald avatar Apr 13 '18 07:04 SvenEwald