xerces-j-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From juho <j.houll...@gmail.com>
Subject Re: Add namespaces declaration to parent element.
Date Thu, 20 Aug 2009 11:47:32 GMT

Hi, 

It isn't for transformation because i need to create a Xml from an XSD and
not parse an existant one.
I use Xerces-J because it permits to validate dynamicly.

I have an Jtree (Java swing) which represents the DOM document.
For each add modify or remove from TreeEditor i validate Dom and DOM Level 3
errorHandler permits me to add on Element is it has an eror , and i show red
text for element with errors.

http://www.nabble.com/file/p25060543/Example.jpg  

and for code :

This is my class which creates Document and permit to serialize it or parse
an other as input :
package org.tdf.tpegPlugin.parser;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.apache.xerces.xs.ElementPSVI;
import org.apache.xerces.xs.XSComplexTypeDefinition;
import org.apache.xerces.xs.XSElementDeclaration;
import org.apache.xerces.xs.XSTypeDefinition;
import org.jdom.Namespace;
import org.tdf.tpegPlugin.TpegPlugin;
import org.tdf.tpegPlugin.exceptions.XSDValidationException;
import org.tdf.tpegPlugin.types.AttributeDescriptor;
import org.tdf.tpegPlugin.types.Descriptor;
import org.tdf.tpegPlugin.types.ElementDescriptor;
import org.tdf.tpegPlugin.util.PropertyConf;
import org.tdf.tpegPlugin.util.XSDNameUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.sun.xml.xsom.XSElementDecl;
import com.sun.xml.xsom.XSSchema;
import com.sun.xml.xsom.XSSchemaSet;

public class DocumentBuilderFromXSD {

	public static Document document;//DOM document
	public Element root;//root element
	public ElementDescriptor rootDesc;//root element descriptor
	public XSSchemaSet schemaSet;//XSD schema representation
	public String rootName;//root name from property file
	private String defaultTargetNamespace = null;//defaultTargzetnamespace use
to validate import.

	private DOMLSParser domParser;
	private ArrayList<String> namespacesList = new ArrayList<String>();
	public static HashMap<String,String> namespaces = new HashMap<String,
String>();//Map namespaceURI to their prefix

	public enum STATE{
		LOAD,CREATE
	}

	public static STATE state= STATE.CREATE;

	/**
	 * Constructor
	 * @param rootName
	 * @param schemaSet
	 */
	public DocumentBuilderFromXSD(String rootName,XSSchemaSet schemaSet){
		this.rootName = rootName;
		this.schemaSet = schemaSet;
		domParser = new DOMLSParser(PropertyConf.getInstance().XSDRoot);
		createNamespace();
		createDocument();
		createRoot();
	}

	/**
	 * Extract namespaces from XSD schema, find if prefix are define in
properties files and keep them in Map.
	 */
	public void createNamespace(){
		defaultTargetNamespace = null;
		boolean isDefaultNamespaceFound = false;
		for(XSSchema schema : schemaSet.getSchemas()){
			String names =schema.getTargetNamespace();
			namespacesList.add(names);
			String prefix = PropertyConf.getInstance().getNamespace(names);
			if(prefix == null )
				continue;
			if(prefix.equals("") && !isDefaultNamespaceFound){
				defaultTargetNamespace = names;
				isDefaultNamespaceFound = true;
			}

			namespaces.put(names, prefix);
		}

		if(namespaces.get("http://www.w3.org/2001/XMLSchema-instance") == null)
			namespaces.put("http://www.w3.org/2001/XMLSchema-instance","xsi");

	}


	/**
	 * Create a document object
	 * using which we create a xml tree in memory
	 */
	private void createDocument() {
		document = domParser.createDocument();

	}


	/**
	 * Create the root Element from XSD schema
	 */
	private void createRoot(){
		try{
			rootDesc = getRoot(rootName);
			root = createElement(rootDesc ,null,-1);
		}
		catch(Exception e){
			TpegPlugin.createDialog(e);
		}
	}

	/**
	 * Find Root element in XSD and return it descriptor. 
	 * 
	 * @param name
	 * @return element descriptor of root element from root name property
	 * @throws XSDValidationException 
	 */
	public ElementDescriptor getRoot(String name) throws
XSDValidationException{

		Collection<XSSchema> schemas = schemaSet.getSchemas();
		Map<String,XSElementDecl> map;
		for(XSSchema schema : schemas){
			map = schema.getElementDecls();
			if( map != null && map.size()>0){
				for (XSElementDecl decl : map.values()){
					if(decl.getName().equals(name))
						return new ElementDescriptor(decl,decl.getType());
				}
			}
		}
		throw new XSDValidationException("Validation error, no root with name
:"+name+" in XSD schema");
	}
	/**
	 * Load an XML file which should be valid 
	 * @param filePath
	 */
	public void loadXML(String filePath){

		root=null;
		document = null;

		try{
			document = loadAndValidate(filePath);
		}
		catch (Exception e) {
			TpegPlugin.createDialog(e);
		}

		if(document != null){
			try{
				rootDesc = getRoot(document.getDocumentElement().getNodeName());
			}
			catch(Exception e){
				TpegPlugin.createDialog(e);
			}
			root = document.getDocumentElement();
		}

	}

	private Document loadAndValidate(String filePath) throws Exception{
//		DOMParser builder = new DOMParser();  
//		//		builder.setIgnoringElementContentWhitespace(true); 
//		builder.setFeature("http://xml.org/sax/features/validation", true);
//	
builder.setFeature("http://apache.org/xml/features/validation/schema",true);
//		//	
builder.setFeature("http://apache.org/xml/features/dom/include-ignorable-whitespace",false);
//	
builder.setProperty("http://apache.org/xml/properties/dom/document-class-name",
"org.apache.xerces.dom.PSVIDocumentImpl");
//
//		// if a targetNamespace is associated to the xsd, pass it to the parseur
//		if(defaultTargetNamespace != null){
//		
builder.setProperty("http://apache.org/xml/properties/schema/external-schemaLocation",
//					defaultTargetNamespace+ " "+ PropertyConf.getInstance().XSDRoot);
//		}
//		else
//		
builder.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation",
//					PropertyConf.getInstance().XSDRoot);
		
		return domParser.parse(filePath);

	}
	/**
	 * This method uses Xerces specific classes
	 * prints the XML document to file.
	 */
	public void printToFile(String resultPath){

		validate(null);
		String errors = domParser.getErrors();
		if(errors.length()>0)
			TpegPlugin.createDialog(new Exception(errors.toString()));

		domParser.build(document, resultPath);
	}

	/**
	 * Create an Element from element descriptor and add it to the parent
Element at count index.
	 * @param desc
	 * @param parent
	 * @param count
	 * @return the Element create from the element desciptor and which has bee
added to the parent
	 */
	public Element createElement(ElementDescriptor desc, Element parent,int
count){
		String prefix = namespaces.get(desc.getNamespaceURI());
		if(prefix == null){
			prefix = "";
			namespaces.put(desc.getNamespaceURI(), "");
		}
		//		Namespace ns2 = Namespace.getNamespace(prefix,desc.getNamespaceURI());

		Element child =  document.createElementNS(desc.getNamespaceURI(),
desc.getName() );
		child.setPrefix(prefix);

		if(parent != null){
			int index =0;
			NodeList children = parent.getChildNodes();
			if (count >0){
				for(int i=0;i<children.getLength();i++){
					Node n = children.item(i);
					if(count == 0)
						break;
					if(n instanceof Element){
						count--;
					}
					index++;
				}
			}
			Node before = children.item(index);
			parent.insertBefore(child, before);
			String parentURI = parent.getNamespaceURI() != null ?
parent.getNamespaceURI() : "";


			//Part which doesn't be ok.
//			if(!parentURI.equals(desc.getNamespaceURI())){
////				Attr xmlnsPrefix =
document.createAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, prefix);
////		xmlnsPrefix.setValue(desc.getNamespaceURI());
//			
parent.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI,prefix,desc.getNamespaceURI());
//			}

			if(desc.extensionsTypes.size()>0){
				prefix = namespaces.get("http://www.w3.org/2001/XMLSchema-instance");
				//				Namespace ns =
Namespace.getNamespace(prefix,"http://www.w3.org/2001/XMLSchema-instance");

				String attrName =
XSDNameUtils.xsTypeNameWithPrefix(desc.getInstanciateTypeDescriptor());

				Attr type =
document.createAttributeNS("http://www.w3.org/2001/XMLSchema-instance",
"type");
				type.setPrefix(prefix);
				type.setValue(attrName);
				child.setAttributeNodeNS(type);

			}
		}


		else
			document.appendChild(child);


		setMandatories(child,desc,validate(child));
		return child;
	}

	/**
	 * Find attributes for an element name and and attributees to the Java
Element representation
	 */
	private void setMandatories(Element elt,ElementDescriptor
desc,XSElementDeclaration type){
		XSComplexTypeDefinition typeDef = null;
		if(type != null ){
			short typeSh = type.getTypeDefinition().getTypeCategory();
			if(typeSh == XSTypeDefinition.COMPLEX_TYPE)
				typeDef = (XSComplexTypeDefinition)type.getTypeDefinition();
		}


		if(typeDef != null){
			boolean isAbstract  =  typeDef.getAbstract();
			System.out.println("Type of elt is abstract :"+isAbstract);
		}

		//Add attributes
		ArrayList<Descriptor> attributes = desc.getNextAttributes(null);
		AttributeDescriptor attr;
		for (Descriptor descriptor : attributes){
			attr = (AttributeDescriptor)descriptor;
			if(attr.isRequired()){
				Namespace ns =
Namespace.getNamespace(namespaces.get(attr.getNamespaceURI()),
attr.getNamespaceURI());
				if(ns != null && !ns.getPrefix().equals(""))
					elt.setAttributeNS(attr.getNamespaceURI(),
attr.getName(),attr.getValue());
				else
					elt.setAttributeNS("",attr.getName(), attr.getValue());

			}
		}

		//Add elements
		ArrayList<Descriptor> elements = desc.getNextElements(null);
		if(elements == null){
			return;
		}
		ElementDescriptor eltDesc;
		for (Descriptor descriptor : elements){
			eltDesc = (ElementDescriptor)descriptor;
			if(eltDesc.isMandatory()){
				int count = 0;
				int size = elt.getChildNodes().getLength();
				if(size>0)
					count = size;
				for(int i=0;i<eltDesc.minOccurs;i++){
					createElement(eltDesc, elt,count);
					count++;
				}
			}
		}
	}


	public XSElementDeclaration validate(Element elt){
		cleanErrors(document);
		document.normalizeDocument();
		if(elt == null)
			return null;

		ElementPSVI elementPSVI=(ElementPSVI) elt;
		XSElementDeclaration declaration = elementPSVI.getElementDeclaration();

		if(declaration==null){
			System.out.println("declaration==null //4");
		}
		return declaration;
	}
	
	private void cleanErrors(Node n){
		NodeList list = n.getChildNodes();
		if(list != null){
			for(int i=0; i<list.getLength(); i++){
				Node child = list.item(i);
				child.setUserData("errors", null, null);
				cleanErrors(child);
			}
		}
		
		NamedNodeMap map = n.getAttributes();
		if(map != null){
			for(int j=0;j<map.getLength();j++){
				Node attr = map.item(j);
				attr.setUserData("errors", null, null);
			}

			n.setUserData("errors", null, null);
		}
	}
}
 





Mukul Gandhi wrote:
> 
> do you already have the old XML format, and only transformation is
> required, to the new format? if yes, I would try to do this with XSLT.
> 
> if you are creating the new XML, as part of some program, where use of
> Xerces-J is mandatory, then we must find way to solve this problem
> with Xerces-J and an API like DOM (which looks like, you are using).
> 
> I think, it would be good, if you can pls share some of the core logic
> you have written using Xerces-J. I think, that would give us some
> insight, about what could be wrong with the logic you have written.
> 
> On Thu, Aug 20, 2009 at 2:27 PM, juho<j.houllier@gmail.com> wrote:
>>
>> Hello,
>>
>> I want to add namespaces declaration on parent if child and parent have
>> different namespaces.
>> My wish is to have output like that:
>>
>> <balise1 xmlns:tec="http://test1">
>>  <tec:balise2 />
>>  <tec:balise3 />
>> </balise>
>>
>> instead of what i have actually
>> <balise1>
>>  <tec:balise2 xmlns:tec="http://test1"/>
>>  <tec:balise3 xmlns:tec="http://test1"/>
>> </balise1>
> 
> 
> 
> -- 
> Regards,
> Mukul Gandhi
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: j-users-unsubscribe@xerces.apache.org
> For additional commands, e-mail: j-users-help@xerces.apache.org
> 
> 
> 

-- 
View this message in context: http://www.nabble.com/Add-namespaces-declaration-to-parent-element.-tp25058380p25060543.html
Sent from the Xerces - J - Users mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: j-users-unsubscribe@xerces.apache.org
For additional commands, e-mail: j-users-help@xerces.apache.org


Mime
View raw message