views:

60

answers:

1

hi,

first time dealing with xml, so please be patient. the code below is probably evil in a million ways (I'd be very happy to hear about all of them), but the main problem is of course that it doesn't work :-)

public class Test {

    private static final String JSDL_SCHEMA_URL = "http://schemas.ggf.org/jsdl/2005/11/jsdl";
    private static final String JSDL_POSIX_APPLICATION_SCHEMA_URL = "http://schemas.ggf.org/jsdl/2005/11/jsdl-posix";

    public static void main(String[] args) {
        System.out.println(Test.createJSDLDescription("/bin/echo", "hello world"));
    }    


    private static String createJSDLDescription(String execName, String args) {
        Document jsdlJobDefinitionDocument = getJSDLJobDefinitionDocument();
        String xmlString = null;

        // create the elements
        Element jobDescription = jsdlJobDefinitionDocument.createElement("JobDescription");
        Element application = jsdlJobDefinitionDocument.createElement("Application");
        Element posixApplication = jsdlJobDefinitionDocument.createElementNS(JSDL_POSIX_APPLICATION_SCHEMA_URL, "POSIXApplication");
        Element executable = jsdlJobDefinitionDocument.createElement("Executable");
        executable.setTextContent(execName);
        Element argument = jsdlJobDefinitionDocument.createElement("Argument");
        argument.setTextContent(args);

        //join them into a tree
        posixApplication.appendChild(executable);
        posixApplication.appendChild(argument);
        application.appendChild(posixApplication);
        jobDescription.appendChild(application);
        jsdlJobDefinitionDocument.getDocumentElement().appendChild(jobDescription);

        DOMSource source = new DOMSource(jsdlJobDefinitionDocument);
        validateXML(source);

        try {
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            StreamResult result = new StreamResult(new StringWriter());
            transformer.transform(source, result);
            xmlString = result.getWriter().toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return xmlString;
    }

    private static Document getJSDLJobDefinitionDocument() {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = null;
        try {
            builder = factory.newDocumentBuilder();
        } catch (Exception e) {
            e.printStackTrace();
        }
        DOMImplementation domImpl = builder.getDOMImplementation();
        Document theDocument = domImpl.createDocument(JSDL_SCHEMA_URL, "JobDefinition", null);
        return theDocument;
    }

    private static void validateXML(DOMSource source) {
        try {
            URL schemaFile = new URL(JSDL_SCHEMA_URL);
        Sche    maFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            Schema schema = schemaFactory.newSchema(schemaFile);
            Validator validator = schema.newValidator();
            DOMResult result = new DOMResult();
            validator.validate(source, result);
            System.out.println("is valid");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

it spits out a somewhat odd message:

org.xml.sax.SAXParseException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'JobDescription'. One of '{"http://schemas.ggf.org/jsdl/2005/11/jsdl":JobDescription}' is expected.

Where am I going wrong here?

Thanks a lot

+3  A: 

I think you are missing the namespace on your elements. Rather than calling createElement(), you can try

document.createElementNS(JSDL_SCHEMA_URL, elementName)

If necessary, you may need to use a prefix, e.g.

document.createElementNS(JSDL_SCHEMA_URL, "jsdl:"+elementName)
mdma
blast. it would seem you are correct, sir. Changing createElement to createElementNS solves it. I thought it was implicit... I wonder though if there's a prettier way to do this?
jd
None that I know of - in the DOM namespaces are not inferred from context - each element must define it's namespace. To make it prettier, you could create a small createElement(String name) wrapper method in your class that calls the full createElementNS on the document.
mdma