I'm trying to generate an XML file with JAXB Annotations
So, i'll generate the JAXB Classes & the package-info.java from the XSD
Lets go :
1 - Package-info.java
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
// See http://java.sun.com/xml/jaxb
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2017.01.05 at 01:51:40 PM CET
//
#XmlSchema(
xmlns = {
#XmlNs(namespaceURI = "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2", prefix = "cac"),
#XmlNs(namespaceURI = "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2", prefix = "cbc"),
#XmlNs(namespaceURI = "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2", prefix = "") //this must be empty prefix
},
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.audaxis.compiere.osg.ei.ubl2;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlSchema;
2 - then I generate an XML with the folowing code :
JAXBContext context = JAXBContext.newInstance(InvoiceType.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
m.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, TUEInvoiceConstants.UBLInvoiceShcemaLocation);
// Write to File
File f = new File(System.getProperty("java.io.tmpdir"), getOutputFileNameSimple(root));
m.marshal(root, f);
3 - result Generated XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Invoice
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:ns11="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xsi:schemaLocation="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 UBL-Invoice-2.1.xsd">
<cbc:UBLVersionID>2.1</cbc:UBLVersionID>
<-- XML tags -->
<END XML>
4 - As you can see, the third namespace was created with a prefix = ns11 , this will cause problems for me in the next step.
Question : How can i let it generate the XML without any prefixes ??
Related
I want to marshal into xml like this:
<?xml version='1.0' encoding='UTF-8'?>
<ns1:rootElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="some_location" xmlns:ns1="namespace1"
xmlns:ns2="namespace2">
<ns1:firstElement>some text</ns1:firstElement>
<ns1:secondElement>
<ns2:otherElement>some text</ns2:otherElement>
...
<ns2:nElement>
<ns2:innerElement>
<ns2:otherInnerElement>some text</ns2:otherInnerElement>
</ns2:innerElement>
</ns2:nElement>
</ns1:secondElement>
</ns1:rootElement>
There are 2 namespaces. The first one is only for rootElement and direct root element. The second namespace is for other huge number of elements with recursion.
How can I describe this without annotating each elements (tags) for namespace2?
I put root class in one package with package-info like that:
#XmlSchema(
namespace = "namespace1",
elementFormDefault = XmlNsForm.QUALIFIED,
xmlns = {
#XmlNs(prefix = "ns1", namespaceURI = "namespace1")
}
)
And other classes I put in another package with own package-info:
#XmlSchema(
namespace = "namespace2",
elementFormDefault = XmlNsForm.QUALIFIED,
xmlns = {
#XmlNs(prefix = "ns2", namespaceURI = "namespace2")
}
)
I have an object which I write to an xml. The xml has escape characters like "&", "<" etc. Now before I process this xml I want a utility to escape these special characters so that the resultant xml has & followed by "amp;" for "&" and "&" followed by "lt;" for "<". I tried StringUtils, XMLWriter and few more but they convert the "<" in opening and closing tags as well which I dont want. I only want "<" in the attribute values to be replaced. Please help.
Example;
I have the input xml as this
<?xml version="1.0" encoding="UTF-8"?>
<personName><firstName>Sam & Pat </firstName>
<sal> > than 10000 </sal>
</personName>
And the expected xml should be `
<?xml version="1.0" encoding="UTF-8"?>
<personName><firstName>Sam & Pat </firstName>
<sal> < than 10000 </sal>
</personName>
If I am using StringUtils, it converts all the "<" characters like this
<sal> < than 10000 </sal>
EDIT: I can't actually use JaxB. I am using FreeMarkerTemplate to do this. Here is the code .
File tempFile = File.createTempFile(fileName, ".tmp");
try (FileWriter writer = new FileWriter(tempFile)) {
freeMarkerConfig.setOutputEncoding(UTF_8);
Template template = freeMarkerConfig.getTemplate(templateName);
template.process(data, writer);
} `
The resultant file which get created should have the handled escape characters.
You can also use Apache Commons Lang Library for escaping the characters:
Example:
String escapeString1 = "Sam & Pat ";
System.out.println("Escaped : " + StringEscapeUtils.escapeXml11(escapeString1));
String escapeString2 = " > than 10000";
System.out.println("Escaped : " + StringEscapeUtils.escapeXml11(escapeString2));
Output:
Escaped : Sam & Pat
Escaped : > than 10000
You can use JAXB for the XML generation. Annotate your Model-Class with #XmlRootElement
Then you can use JAXB for marshalling the XML-Object:
try {
JAXBContext context = JAXBContext.newInstance(Person.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Person object = new Person();
object.setPersonName("Sam & Pat");
object.setSal("> than 10000");
m.marshal(object, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
The output will be
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
<personName>Sam & Pat</personName>
<sal>> than 10000</sal>
</person>
Using CDATA will fix your problem.
Such as <![CDATA[abc]]>
You can include XML special characters in XPL. XPL has exactly the same structure as XML, but allows the special characters in text fields. http://hll.nu/
Background
Using JDK 6 to load XML files into DOM. The XML files must be validated against an XSD. The XSD file location differs depending on the running environment. Ensuring the XML can be validated against an XSD, regardless of directory structure, requires a catalog resolver. Once the XML is validated, it can then be transformed.
My understanding is that a DocumentBuilderFactory can be used to configure such validation. This is achieved by using a DocumentBuilder with an XMLCatalogResolver to find the XSD file (and any included files) associated with an XML file.
Questions about validating XML documents using a catalog-derived XSD, include:
JAXP - debug XSD catalog look up
Java XML Schema validator with custom resource resolver fails to resolve elements
Can XMLCatalog be used for schema imports?
How to load XMLCatalog from classpath resources (inside a jar), reliably?
XMLSchema validation with Catalog.xml file for entity resolving
Resolving type definitions from imported schema in XJC fails
Find items that can be repeated in an xml schema using Java
Java servlets: xml validation against xsd
Most of these questions and answers reference a hard-coded XSD file path, or use SAX to perform the validation, or pertain to DTDs, or require JDOM dependencies, or have no transformation.
Problem
There is no canonical solution that describes how to employ an XML catalog for XSD validation using JAXP DOM, that is subsequently transformed via XSLT. There are a number of snippets, but no complete, standalone example that compiles and runs (under JDK 6).
I posted an answer that seems to work, technically, but is overly verbose.
Question
What is the canonical way (using JDK 1.6 libraries) to validate and transform an XML document? Here is one possible algorithm:
Create a catalog resolver.
Create an XML parser.
Associate the resolver with the parser.
Parse an XML document containing an XSD reference.
Terminate on validation errors.
Transform the validated XML using an XSL template.
Source Files
The source files include a catalog manager properties file, Java source code, catalog file, XML data, XSL files, and XSD files. All files are relative to the current working directory (./).
Catalog Manager Properties File
This properties file is read by the CatalogResolver class; save as ./CatalogManager.properties:
catalogs=catalog.xml
relative-catalogs=yes
verbosity=99
prefer=system
static-catalog=yes
allow-oasis-xml-catalog-pi=yes
TestXSD.java
This is the main application; save it as ./src/TestXSD.java:
package src;
import java.io.*;
import java.net.URI;
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import javax.xml.parsers.*;
import javax.xml.xpath.*;
import javax.xml.XMLConstants;
import org.w3c.dom.*;
import org.xml.sax.*;
import org.apache.xml.resolver.tools.CatalogResolver;
import org.apache.xerces.util.XMLCatalogResolver;
import static org.apache.xerces.jaxp.JAXPConstants.JAXP_SCHEMA_LANGUAGE;
import static org.apache.xerces.jaxp.JAXPConstants.W3C_XML_SCHEMA;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Schema;
import javax.xml.validation.Validator;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
/**
* Download http://xerces.apache.org/xml-commons/components/resolver/CatalogManager.properties
*/
public class TestXSD {
private final static String ENTITY_RESOLVER =
"http://apache.org/xml/properties/internal/entity-resolver";
/**
* This program reads an XML file, performs validation, reads an XSL
* file, transforms the input XML, and then writes the transformed document
* to standard output.
*
* args[0] - The XSL file used to transform the XML file
* args[1] - The XML file to transform using the XSL file
*/
public static void main( String args[] ) throws Exception {
// For validation error messages.
ErrorHandler errorHandler = new DocumentErrorHandler();
// Read the CatalogManager.properties file.
CatalogResolver resolver = new CatalogResolver();
XMLCatalogResolver xmlResolver = createXMLCatalogResolver( resolver );
logDebug( "READ XML INPUT SOURCE" );
// Load an XML document in preparation to transform it.
InputSource xmlInput = new InputSource( new InputStreamReader(
new FileInputStream( args[1] ) ) );
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
dbFactory.setAttribute( JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA );
dbFactory.setNamespaceAware( true );
DocumentBuilder builder = dbFactory.newDocumentBuilder();
builder.setEntityResolver( xmlResolver );
builder.setErrorHandler( errorHandler );
logDebug( "PARSE XML INTO DOCUMENT MODEL" );
Document xmlDocument = builder.parse( xmlInput );
logDebug( "CONVERT XML DOCUMENT MODEL INTO DOMSOURCE" );
DOMSource xml = new DOMSource( xmlDocument );
logDebug( "GET XML SCHEMA DEFINITION" );
String schemaURI = getSchemaURI( xmlDocument );
logDebug( "SCHEMA URI: " + schemaURI );
if( schemaURI != null ) {
logDebug( "CREATE SCHEMA FACTORY" );
// Create a Schema factory to obtain a Schema for XML validation...
SchemaFactory sFactory = SchemaFactory.newInstance( W3C_XML_SCHEMA );
sFactory.setResourceResolver( xmlResolver );
logDebug( "CREATE XSD INPUT SOURCE" );
String xsdFileURI = xmlResolver.resolveURI( schemaURI );
logDebug( "CREATE INPUT SOURCE XSD FROM: " + xsdFileURI );
InputSource xsd = new InputSource(
new FileInputStream( new File( new URI( xsdFileURI ) ) ) );
logDebug( "CREATE SCHEMA OBJECT FOR XSD" );
Schema schema = sFactory.newSchema( new SAXSource( xsd ) );
logDebug( "CREATE VALIDATOR FOR SCHEMA" );
Validator validator = schema.newValidator();
logDebug( "VALIDATE XML AGAINST XSD" );
validator.validate( xml );
}
logDebug( "READ XSL INPUT SOURCE" );
// Load an XSL template for transforming XML documents.
InputSource xslInput = new InputSource( new InputStreamReader(
new FileInputStream( args[0] ) ) );
logDebug( "PARSE XSL INTO DOCUMENT MODEL" );
Document xslDocument = builder.parse( xslInput );
transform( xmlDocument, xslDocument, resolver );
System.out.println();
}
private static void transform(
Document xml, Document xsl, CatalogResolver resolver ) throws Exception
{
if( versionAtLeast( xsl, 2 ) ) {
useXSLT2Transformer();
}
logDebug( "CREATE TRANSFORMER FACTORY" );
// Create the transformer used for the document.
TransformerFactory tFactory = TransformerFactory.newInstance();
tFactory.setURIResolver( resolver );
logDebug( "CREATE TRANSFORMER FROM XSL" );
Transformer transformer = tFactory.newTransformer( new DOMSource( xsl ) );
logDebug( "CREATE RESULT OUTPUT STREAM" );
// This enables writing the results to standard output.
Result out = new StreamResult( new OutputStreamWriter( System.out ) );
logDebug( "TRANSFORM THE XML AND WRITE TO STDOUT" );
// Transform the document using a given stylesheet.
transformer.transform( new DOMSource( xml ), out );
}
/**
* Answers whether the given XSL document version is greater than or
* equal to the given required version number.
*
* #param xsl The XSL document to check for version compatibility.
* #param version The version number to compare against.
*
* #return true iff the XSL document version is greater than or equal
* to the version parameter.
*/
private static boolean versionAtLeast( Document xsl, float version ) {
Element root = xsl.getDocumentElement();
float docVersion = Float.parseFloat( root.getAttribute( "version" ) );
return docVersion >= version;
}
/**
* Enables Saxon9's XSLT2 transformer for XSLT2 files.
*/
private static void useXSLT2Transformer() {
System.setProperty("javax.xml.transform.TransformerFactory",
"net.sf.saxon.TransformerFactoryImpl");
}
/**
* Creates an XMLCatalogResolver based on the file names found in
* the given CatalogResolver. The resulting XMLCatalogResolver will
* contain the absolute path to all the files known to the given
* CatalogResolver.
*
* #param resolver The CatalogResolver to examine for catalog file names.
* #return An XMLCatalogResolver instance with the same number of catalog
* files as found in the given CatalogResolver.
*/
private static XMLCatalogResolver createXMLCatalogResolver(
CatalogResolver resolver ) {
int index = 0;
List files = resolver.getCatalog().getCatalogManager().getCatalogFiles();
String catalogs[] = new String[ files.size() ];
XMLCatalogResolver xmlResolver = new XMLCatalogResolver();
for( Object file : files ) {
catalogs[ index ] = (new File( file.toString() )).getAbsolutePath();
index++;
}
xmlResolver.setCatalogList( catalogs );
return xmlResolver;
}
private static String[] parseNameValue( String nv ) {
Pattern p = Pattern.compile( "\\s*(\\w+)=\"([^\"]*)\"\\s*" );
Matcher m = p.matcher( nv );
String result[] = new String[2];
if( m.find() ) {
result[0] = m.group(1);
result[1] = m.group(2);
}
return result;
}
/**
* Retrieves the XML schema definition using an XSD.
*
* #param node The document (or child node) to traverse seeking processing
* instruction nodes.
* #return null if no XSD is present in the XML document.
* #throws IOException Never thrown (uses StringReader).
*/
private static String getSchemaURI( Node node ) throws IOException {
String result = null;
if( node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE ) {
ProcessingInstruction pi = (ProcessingInstruction)node;
logDebug( "NODE IS PROCESSING INSTRUCTION" );
if( "xml-model".equals( pi.getNodeName() ) ) {
logDebug( "PI IS XML MODEL" );
// Hack to get the attributes.
String data = pi.getData();
if( data != null ) {
final String attributes[] = pi.getData().trim().split( "\\s+" );
String type = parseNameValue( attributes[0] )[1];
String href = parseNameValue( attributes[1] )[1];
// TODO: Schema should = http://www.w3.org/2001/XMLSchema
//String schema = attributes.getNamedItem( "schematypens" );
if( "application/xml".equalsIgnoreCase( type ) && href != null ) {
result = href;
}
}
}
}
else {
// Try to get the schema type information.
NamedNodeMap attrs = node.getAttributes();
if( attrs != null ) {
// TypeInfo.toString() returns values of the form:
// schemaLocation="uri schemaURI"
// The following loop extracts the schema URI.
for( int i = 0; i < attrs.getLength(); i++ ) {
Attr attribute = (Attr)attrs.item( i );
TypeInfo typeInfo = attribute.getSchemaTypeInfo();
String attr[] = parseNameValue( typeInfo.toString() );
if( "schemaLocation".equalsIgnoreCase( attr[0] ) ) {
result = attr[1].split( "\\s" )[1];
break;
}
}
}
// Look deeper for the schema URI.
if( result == null ) {
NodeList list = node.getChildNodes();
for( int i = 0; i < list.getLength(); i++ ) {
result = getSchemaURI( list.item( i ) );
if( result != null ) {
break;
}
}
}
}
return result;
}
/**
* Writes a message to standard output.
*/
private static void logDebug( String s ) {
System.out.println( s );
}
}
Error Handler
This is the code for human-friendly error messages; save as ./src/DocumentErrorHandler.java:
package src;
import java.io.PrintStream;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXParseException;
import org.xml.sax.SAXException;
/**
* Handles error messages during parsing and validating XML documents.
*/
public class DocumentErrorHandler implements ErrorHandler {
private final static PrintStream OUTSTREAM = System.err;
private void log( String type, SAXParseException e ) {
OUTSTREAM.println( "SAX PARSE EXCEPTION " + type );
OUTSTREAM.println( " Public ID: " + e.getPublicId() );
OUTSTREAM.println( " System ID: " + e.getSystemId() );
OUTSTREAM.println( " Line : " + e.getLineNumber() );
OUTSTREAM.println( " Column : " + e.getColumnNumber() );
OUTSTREAM.println( " Message : " + e.getMessage() );
}
#Override
public void error( SAXParseException e ) throws SAXException {
log( "ERROR", e );
}
#Override
public void fatalError( SAXParseException e ) throws SAXException {
log( "FATAL ERROR", e );
}
#Override
public void warning( SAXParseException e ) throws SAXException {
log( "WARNING", e );
}
}
Catalog File
Save as ./catalog.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE catalog PUBLIC "-//OASIS//DTD XML Catalogs V1.1//EN" "http://www.oasis-open.org/committees/entity/release/1.1/catalog.dtd">
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<!-- XSDs linked through primary catalog -->
<!-- catalog entry for good-note1.xml -->
<rewriteSystem
systemIdStartString="http://stackoverflow.com/schema"
rewritePrefix="./ArbitraryFolder/schemas"
/>
<!-- catalog entry for good-note2.xml, good-note3.xml, bad-note1.xml, bad-note2.xml -->
<rewriteURI
uriStartString="http://stackoverflow.com/2014/09/xsd"
rewritePrefix="./ArbitraryFolder/schemas"
/>
<!-- add a second catalog as a further test:
XSL will be resolved through it -->
<nextCatalog
catalog="./ArbitraryFolder/catalog.xml"
/>
</catalog>
XML Data
The different test cases include XSDs referenced in either processing instructions or root nodes.
Schema: Processing Instruction
The schema can be provided using an xml-model processing instruction (PI). Save as ./Tests/good-notes2.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Associating Schemas with XML documents: http://www.w3.org/TR/xml-model/ -->
<?xml-model type="application/xml" href="http://stackoverflow.com/2014/09/xsd/notes/notes.xsd"?>
<note>
<title>Shopping List</title>
<date>2014-08-30</date>
<body>headlight fluid, flamgrabblit, exhaust coil</body>
</note>
Schema: Root Node
The schema can be provided in attributes of the document's root node. Save as ./Tests/good-notes3.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!-- XML Schema Part 1: Structures:
Schema-Related Markup in Documents Being Validated:
http://www.w3.org/TR/xmlschema-1/#Instance_Document_Constructions -->
<note
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://stackoverflow.com http://stackoverflow.com/2014/09/xsd/notes/notes.xsd">
<title>Shopping List</title>
<date>2014-08-30</date>
<body>Eggs, Milk, Carrots</body>
</note>
Fail Validation
The following should fail validation (date needs hyphens); save as ./Tests/bad-note1.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Associating Schemas with XML documents: http://www.w3.org/TR/xml-model/ -->
<?xml-model type="application/xml" href="http://stackoverflow.com/2014/09/xsd/notes/notes.xsd"?>
<!-- FAILS SCHEMA: date is not valid; should use hyphens -->
<note>
<title>Shopping List</title>
<date>20140830</date>
<body>headlight fluid, flamgrabblit, exhaust coil</body>
</note>
Transformation
Save this as ./Tests/note-to-html.xsl:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<!-- is in the second catalog (../ArbitraryFolder/catalog.xml) -->
<xsl:import href="http://stackoverflow.com/2014/09/xsl/notes/notes.xsl"/>
</xsl:stylesheet>
Arbitrary Folder
The arbitrary folder represents the path to files on a computer that can be located anywhere on the file system. The location of these files could differ, for example, between production, development, and the repository.
Catalog
Save this file as ./ArbitraryFolder/catalog.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE catalog PUBLIC "-//OASIS//DTD XML Catalogs V1.1//EN" "http://www.oasis-open.org/committees/entity/release/1.1/catalog.dtd">
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<!-- catalog entry for all notes -->
<rewriteURI
uriStartString="http://stackoverflow.com/2014/09/xsl/"
rewritePrefix="./XSL/"/>
</catalog>
Notes
There are two files in this example for transforming the notes: notes.xsl and note-body.xsl. The first includes the second.
Notes Stylesheet
Save this as ./ArbitraryFolder/XSL/notes/notes.xsl:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<!-- will not be in catalog (though it could be):
by convention, absolute path is assumed to be part of static file structure -->
<xsl:import href="note-body.xsl"/>
<xsl:template match="/">
<html>
<head>
<title>A Note</title>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="note">
<div>
<xsl:apply-templates select="title, date, body"/>
</div>
</xsl:template>
<xsl:template match="title">
<h1><xsl:value-of select="."/></h1>
</xsl:template>
<xsl:template match="date">
<p class="date"><xsl:value-of select="."/></p>
</xsl:template>
</xsl:stylesheet>
Note Body Stylesheet
Save this as ./ArbitraryFolder/XSL/notes/note-body.xsl:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:template match="body">
<p class="notebody"><xsl:value-of select="."/></p>
</xsl:template>
</xsl:stylesheet>
Schema
The last file required is the schema; save this as ./schemas/notes/notes.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="note">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:token"/>
<xs:element name="date" type="xs:date"/>
<xs:element name="body" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Building
This section details how to build the test application.
Libraries
You will need Saxon 9 (for XSLT2.0 documents), Xerces, Xalan, and the Resolver API:
jaxen-1.1.6.jar
resolver.jar
saxon9he.jar
serializer.jar
xalan.jar
xercesImpl.jar
xml-apis.jar
xsltc.jar
Scripts
Save as ./build.sh:
#!/bin/bash
javac -d bin -cp .:lib/* src/TestXSD.java
Save as ./run.sh:
#!/bin/bash
java -cp .:bin:lib/* src.TestXSD Tests/note-to-html.xsl $1
Compile
Use the ./build.sh to compile the code.
Run Output
Run using:
./run.sh filename.xml
Good Test
Test that the good note passes validation:
./run.sh Tests/good-note2.xml
No errors.
Bad Test
Test that the bad note's date does not pass validation:
./run.sh Tests/bad-note1.xml
As expected, this produces the desired error:
Exception in thread "main" org.xml.sax.SAXParseException; cvc-datatype-valid.1.2.1: '20140830' is not a valid value for 'date'.
at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
at org.apache.xerces.util.ErrorHandlerWrapper.error(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaValidator.reportSchemaError(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaValidator.elementLocallyValidType(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaValidator.processElementContent(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaValidator.handleEndElement(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaValidator.endElement(Unknown Source)
at org.apache.xerces.jaxp.validation.DOMValidatorHelper.finishNode(Unknown Source)
at org.apache.xerces.jaxp.validation.DOMValidatorHelper.validate(Unknown Source)
at org.apache.xerces.jaxp.validation.DOMValidatorHelper.validate(Unknown Source)
at org.apache.xerces.jaxp.validation.ValidatorImpl.validate(Unknown Source)
at javax.xml.validation.Validator.validate(Validator.java:124)
at src.TestXSD.main(TestXSD.java:103)
I am getting the error "The prefix "c" for element "c:de" is not bound." Any clue will be very appreciated.
javax.xml.parsers.DocumentBuilderFactory fac = new org.apache.xerces.jaxp.DocumentBuilderFactoryImpl( );
fac.setNamespaceAware(true);
org.w3c.dom.Document d = null;
javax.xml.parsers.DocumentBuilder builder = fac.newDocumentBuilder();
d = builder.parse("C:/my_folder/my_file.xml"); //the error rises in this line
my_file.xml is exactly and complete pasted here.
<?xml version="1.0" encoding="UTF-8"?>
<c:de format="N" lengthField="0" maxLength="012" minLength="012" name="AMOUNT, TRANSACTION" number="004" subFields="00"/>
Your XML is technically invalid.
The namespace prefix c "MUST be associated with a namespace URI reference in a namespace declaration." (W3). For example, this would work:
<?xml version="1.0" encoding="UTF-8"?>
<c:de xmlns:c="http://localhost/" format="N" lengthField="0" maxLength="012" minLength="012" name="AMOUNT, TRANSACTION" number="004" subFields="00"/>
Note the addition of the xmlns:c attribute. The URI you use in this attribute should be the one that properly identifiies the namespace you intend to use.
i have some user defined tag. for example data here , jssj .I have a file(not xml) which contains some data embeded in tags.I need a parser for this which will identify my tags and will extract the data in proper format.
Eg
<newpage> thix text </newpage>
<tagD>
<tagA> kk</tagA>
</tagD>
tags can also have some attributes as simlar to html tags. Eg
<mytag height="f" width ="d" > bla bla bla </mytag>
<mytag attribute="val"> bla bla bla</mytag>
You could look at a parser generator like antlr.
Unless your tag syntax can be represented with a (simple) regular grammar (in which case you could try to scan the file with regexes), you will need a proper parser. It is actually not very hard to do at all - just the first time tastes like biting bullets...
You can use JAXB, already included in Java. It's quite simple.
First you need to create a binding to your XML code. The binding provides a map between Java objects and the XML code.
An example would be:
#XmlRootElement(name = "YourRootElement", namespace ="http://someurl.org")
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"intValue",
"stringArray",
"stringValue"}
)
public class YourBindingClass {
protected int intValue;
#XmlElement(nillable = false)
protected List<String> stringArray;
#XmlElement(name = "stringValue", required = true)
protected String stringValue;
public int getIntValue() {
return intValue;
}
public void setIntValue(int value) {
this.intValue = value;
}
public List<String> getStringArray() {
if (stringArray == null) {
stringArray = new ArrayList<String>();
}
return this.stringArray;
}
public String getStringValue() {
return stringValue;
}
public void setStringValue(String value) {
this.stringValue = value;
}
}
Then, to encode your Java objects into XML, you can use:
YourBindingClass yourBindingClass = ...;
JAXBContext jaxbContext = JAXBContext.newInstance(YourBindingClass.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);
/** If you need to specify a schema */
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new URL("http:\\www.someurl.org"));
marshaller.setSchema(schema);
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, true);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
marshaller.marshal(yourBindingClass, stream);
System.out.println(stream);
To parse your XML back to objects:
InputStream resourceAsStream = ... // Your XML, File, etc.
JAXBContext jaxbContext = JAXBContext.newInstance(YourBindingClass.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Object r = unmarshaller.unmarshal(resourceAsStream);
if (r instanceof YourBindingClass) ...
Example starting from a Java object:
YourBindingClass s = new YourBindingClass();
s.setIntValue(1);
s.setStringValue("a");
s.getStringArray().add("b1");
s.getStringArray().add("b2");
// marshal ...
Result:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:YourRootElement xmlns:ns2="http://someurl.org">
<intValue>1</intValue>
<stringArray>b1</stringArray>
<stringArray>b2</stringArray>
<stringValue>a</stringValue>
</ns2:YourRootElement>
If you don't know the input format, that means you probably don't have a XML schema. If you don't have a schema you don't have some it's benefits such as:
It is easier to describe allowable document content
It is easier to validate the correctness of data
It is easier to define data facets (restrictions on data)
It is easier to define data patterns (data formats)
It is easier to convert data between different data types
Anyway, the previous code also works with XML code that contains 'unknown' tags. However your XML code still have to present the required fields and follow the declared patterns.
So the following XML code is also valid. The only restriction is: the tag 'stringValue' should be there. Note that 'stringArrayQ' was not previously declared.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:YourRootElement xmlns:ns2="http://someurl.org">
<stringValue>a</stringValue>
<stringArrayQ>b1</stringArrayQ>
</ns2:YourRootElement>
Are these XML tags? If so, look into one of the many Java XML libraries already available. If they're some kind of custom tagging format, then you're just going to have to write it yourself.
For xml tags - use DOM parser or SAX parser.
You example is XML with this modification:
<root>
<newpage> thix text </newpage>
<tagD>
<tagA> kk</tagA>
</tagD>
</root>
You can use any XML parser you want to parse it.
Edit:
Attributes are a normal part of XML.
<root>
<newpage> thix text </newpage>
<tagD>
<tagA> kk</tagA>
</tagD>
<mytag height="f" width ="d" > bla bla bla </mytag>
<mytag attribute="val"> bla bla bla</mytag>
</root>
Every XML parser can deal with them.
Edit:
If you were able to use Python, you could do something like this:
import lxml.etree
doc = lxml.etree.parse("foo.xml")
print doc.xpath("//mytag[1]/#width")
# => ['d']
That's what i call simple.