Assume there's an XMLBeans XmlObject with attributes, how can I get selected attributes in single step?
I'm expecting like something ....
removeAttributes(XmlObject obj, String[] selectableAttributes){};
Now the above method should return me the XMLObject with only those attributes.
Assumption: the attributes that you want to remove from your XmlObject must be optional in the corresponding XML Schema. Under this assumption, XMLBeans provides you with a couple of useful methods: unsetX and isSetX (where X is your attribute name. So, we can implement a removeAttributes method in this way:
public void removeAttributes(XmlObject obj,
String[] removeAttributeNames)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException, SecurityException,
NoSuchMethodException {
Class<?> clazz = obj.getClass();
for (int i = 0; i < removeAttributeNames.length; i++) {
String attrName =
removeAttributeNames[i].substring(0, 1).toUpperCase() +
removeAttributeNames[i].substring(1);
String isSetMethodName = "isSet" + attrName;
Boolean isSet = null;
try {
Method isSetMethod = clazz.getMethod(isSetMethodName);
isSet = (Boolean) isSetMethod.invoke(obj, new Object[] {});
} catch (NoSuchMethodException e) {
System.out.println("attribute " + removeAttributeNames[i]
+ " is not optional");
}
if (isSet != null && isSet.booleanValue() == true) {
String unsetMethodName = "unset" + attrName;
Method unsetMethod = clazz.getMethod(unsetMethodName);
unsetMethod.invoke(obj, new Object[] {});
}
}
}
Note 1: I have slightly modified the semantics of your method signature: the second argument (the String[]) is actually the list of attributes that you want to remove. I think this is more consistent with the method name (removeAttributes), and it also simplify things (using unsetX and isSetX).
Note 2: The reason for calling isSetX before calling unsetX is that unsetX would throw an InvocationTargetException if called when the attribute X is not set.
Note 3: You may want to change exception handling according to your needs.
I think you can use a cursor ... they are cumbersome to handle, but so is reflection.
public static XmlObject RemoveAllAttributes(XmlObject xo) {
return RemoveAllofType(xo, TokenType.ATTR);
}
public static XmlObject RemoveAllofTypes(XmlObject xo, final TokenType... tts) {
printTokens(xo);
final XmlCursor xc = xo.newCursor();
while (TokenType.STARTDOC == xc.currentTokenType() || TokenType.START == xc.currentTokenType()) {
xc.toNextToken();
}
while (TokenType.ENDDOC != xc.currentTokenType() && TokenType.STARTDOC != xc.prevTokenType()) {
if (ArrayUtils.contains(tts, xc.currentTokenType())) {
xc.removeXml();
continue;
}
xc.toNextToken();
}
xc.dispose();
return xo;
}
I am using this simple method to clean everything in the element. You can omit the cursor.removeXmlContents to only delete attributes. Second cursor is used to return to the initial position:
public static void clearElement(final XmlObject object)
{
final XmlCursor cursor = object.newCursor();
cursor.removeXmlContents();
final XmlCursor start = object.newCursor();
while (cursor.toFirstAttribute())
{
cursor.removeXml();
cursor.toCursor(start);
}
start.dispose();
cursor.dispose();
}
Related
In here im logging the changes that has been done to a particular Object record. So im comparing the old record and the updated record to log the updated fields as a String. Any idea how can I do this?
Well i found a solution as below :
private static List<String> getDifference(Object s1, Object s2) throws IllegalAccessException {
List<String> values = new ArrayList<>();
for (Field field : s1.getClass().getDeclaredFields()) {
field.setAccessible(true);
Object value1 = field.get(s1);
Object value2 = field.get(s2);
if (value1 != null && value2 != null) {
if (!Objects.equals(value1, value2)) {
values.add(String.valueOf(field.getName()+": "+value1+" -> "+value2));
}
}
}
return values;
}
You may use javers library for this.
<groupId>org.javers</groupId>
<artifactId>javers-core</artifactId>
POJO:
public class Person {
private Integer id;
private String name;
// standard getters/constructors
}
Usage:
#Test
public void givenPersonObject_whenApplyModificationOnIt_thenShouldDetectChange() {
// given
Javers javers = JaversBuilder.javers().build();
Person person = new Person(1, "Michael Program");
Person personAfterModification = new Person(1, "Michael Java");
// when
Diff diff = javers.compare(person, personAfterModification);
// then
ValueChange change = diff.getChangesByType(ValueChange.class).get(0);
assertThat(diff.getChanges()).hasSize(1);
assertThat(change.getPropertyName()).isEqualTo("name");
assertThat(change.getLeft()).isEqualTo("Michael Program");
assertThat(change.getRight()).isEqualTo("Michael Java");
}
Plus other use cases are supported as well.
maybe this method can help you to solve you problem
/**
* get o1 and o2 different value of field name
* #param o1 source
* #param o2 target
* #return
* #throws IllegalAccessException
*/
public static List<String> getDiffName(Object o1,Object o2) throws IllegalAccessException {
//require o1 and o2 is not null
if (o1==null&&o2==null){
return Collections.emptyList();
}
//if only one has null
if (o1 == null){
return getAllFiledName(o2);
}
if (o2 == null){
return getAllFiledName(o1);
}
//source field
Field[] fields=o1.getClass().getDeclaredFields();
List<String> fieldList=new ArrayList<>(fields.length);
//if class is same using this to call
if (o1.getClass().equals(o2.getClass())){
//loop field to equals the field
for (Field field : fields) {
//to set the field access
field.setAccessible(true);
Object source = field.get(o1);
Object target = field.get(o2);
//using jdk8 equals to compare two objects
if (!Objects.equals(source, target)){
fieldList.add(field.getName());
}
}
}else {
//maybe o1 class is not same as o2 class
Field[] targetFields=o2.getClass().getDeclaredFields();
List<String> sameFieldNameList=new ArrayList<>();
//loop o1 field
for (Field field : fields) {
String name = field.getName();
//loop target field to get same field
for (Field targetField : targetFields) {
//if name is equal to compare
if (targetField.getName().equals(name)){
//add same field to list
sameFieldNameList.add(name);
//set access
field.setAccessible(true);
Object source = field.get(o1);
//set target access
targetField.setAccessible(true);
Object target = targetField.get(o2);
//equals
if (!Objects.equals(source, target)){
fieldList.add(field.getName());
}
}
}
}
//after loop add different source
for (Field targetField : targetFields) {
//add not same field
if (!sameFieldNameList.contains(targetField.getName())){
fieldList.add(targetField.getName());
}
}
}
return fieldList;
}
/**
* getAllFiledName
* #param obj
* #return
*/
private static List<String> getAllFiledName(Object obj) {
Field[] declaredFields = obj.getClass().getDeclaredFields();
List<String> list=new ArrayList<>(declaredFields.length);
for (Field field : declaredFields) {
list.add(field.getName());
}
return list;
}
this method can compare two object which have the same name field ,if they don't have same field,return all field Name
Kotlin generic function with reflection
It's not a perfect answer to this question, but maybe someone could use it.
data class Difference(val old: Any?, val new: Any?)
fun findDifferencesInObjects(
old: Any,
new: Any,
propertyPath: String? = null
): MutableMap<String, Difference> {
val differences = mutableMapOf<String, Difference>()
if (old::class != new::class) return differences
#Suppress("UNCHECKED_CAST")
old::class.memberProperties.map { property -> property as KProperty1<Any, *>
val newPropertyPath = propertyPath?.plus('.')?.plus(property.name) ?: property.name
property.isAccessible = true
val oldValue = property.get(old)
val newValue = property.get(new)
if (oldValue == null && newValue == null) return#map
if (oldValue == null || newValue == null) {
differences[newPropertyPath] = Difference(oldValue, newValue)
return#map
}
if (oldValue::class.isData || newValue::class.isData) {
differences.putAll(findDifferencesInObject(oldValue, newValue, newPropertyPath))
} else if (!Objects.equals(oldValue, newValue)) {
differences[newPropertyPath] = Difference(oldValue, newValue)
}
}
return differences
}
Result
{
"some.nested.and.changed.field": {
"old": "this value is old",
"new": "this value is new"
},
...
}
Suppose you have this protobuf model:
message ComplexKey {
string name = 1;
int32 domainId = 2;
}
message KeyMsg {
oneof KeyMsgOneOf {
string name = 1;
ComplexKey complexName= 2;
}
}
and an object obj, that you know is either a string or a ComplexKey.
Question
Whitout explicitly checking the obj class type, which is the most efficient way to build a new KeyMsg instance with the obj placed in the correct field using the protobuf Java API?
UPDATE: it would be great if protoc generates an helper method to do what I need.
UPDATE2: given the correct comment from Mark G. below and supposing that all fields differ in type, the best solution I've find so far is (simplified version):
List<FieldDescriptor> lfd = oneOfFieldDescriptor.getFields();
for (FieldDescriptor fieldDescriptor : lfd) {
if (fieldDescriptor.getDefaultValue().getClass() == oVal.getClass()) {
vmVal = ValueMsg.newBuilder().setField(fieldDescriptor, oVal).build();
break;
}
}
You can use switch-case:
public Object demo() {
KeyMsg keyMsg = KeyMsg.newBuilder().build();
final KeyMsg.KeyMsgOneOfCase oneOfCase = keyMsg.getKeyMsgOneOfCase();
switch (oneOfCase) {
case NAME: return keyMsg.getName();
case COMPLEX_NAME: return keyMsg.getComplexName();
case KEY_MSG_ONE_OF_NOT_SET: return null;
}
}
I doubt there is a better way than using instanceof:
KeyMsg.Builder builder = KeyMsg.newBuilder();
if (obj instanceof String) {
builder.setName((String) obj);
} else if (obj instanceof ComplexKey) {
builder.setComplexName((ComplexKey) obj);
} else {
throw new AssertionError("Not a String or ComplexKey");
}
KeyMsg msg = builder.build();
I need to generate an interface at runtime. This interface will be used in a dynamic proxy. At first, I found this article from Google, but then I found I could just use ASM instead. Here is my code that gets the bytecode of the interface:
private static byte[] getBytecode(String internalName, String genericClassTypeSignature, Method[] methods, Class<?>... extendedInterfaces) throws IOException {
ClassWriter cw = new ClassWriter(0);
String[] interfaces = new String[extendedInterfaces.length];
int i = 0;
for (Class<?> interfac : extendedInterfaces) {
interfaces[i] = interfac.getName().replace('.', '/');
i++;
}
cw.visit(V1_6, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, internalName, null, "java/lang/Object", interfaces);
ArrayList<String> exceptions = new ArrayList<String>();
for (Method m : methods) {
exceptions.clear();
for (Class<?> exception : m.getExceptionTypes()) {
exceptions.add(getInternalNameOf(exception));
}
cw.visitMethod(removeInvalidAbstractModifiers(m.getModifiers()) + ACC_ABSTRACT, m.getName(), getMethodDescriptorOf(m), getTypeSignatureOf(m), exceptions.toArray(new String[exceptions.size()]));
}
cw.visitEnd();
return cw.toByteArray();
}
private static int removeInvalidAbstractModifiers(int mod) {
int result = 0;
if (Modifier.isProtected(mod)) {
result += ACC_PROTECTED;
}
if (Modifier.isPublic(mod)) {
result += ACC_PUBLIC;
}
if (Modifier.isTransient(mod)) {
result += ACC_VARARGS;
}
return result;
}
Just for test purposes, I tried to convert JFrame to an interface. But when I load my generated interface, it gives me a java.lang.ClassFormatError:
java.lang.ClassFormatError: Method paramString in class javax/swing/JFrame$GeneratedInterface has illegal modifiers: 0x404
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
at java.lang.ClassLoader.defineClass(ClassLoader.java:634)
// ...
Modifier.toString(0x404) tells me that 0x404 means protected abstract. As far as I know, a protected abstract method in an abstract class is perfectly legal.
Here is the code for the paramString method (see above) in JFrame:
/**
* Returns a string representation of this <code>JFrame</code>.
* This method
* is intended to be used only for debugging purposes, and the
* content and format of the returned string may vary between
* implementations. The returned string may be empty but may not
* be <code>null</code>.
*
* #return a string representation of this <code>JFrame</code>
*/
protected String paramString() {
String defaultCloseOperationString;
if (defaultCloseOperation == HIDE_ON_CLOSE) {
defaultCloseOperationString = "HIDE_ON_CLOSE";
} else if (defaultCloseOperation == DISPOSE_ON_CLOSE) {
defaultCloseOperationString = "DISPOSE_ON_CLOSE";
} else if (defaultCloseOperation == DO_NOTHING_ON_CLOSE) {
defaultCloseOperationString = "DO_NOTHING_ON_CLOSE";
} else if (defaultCloseOperation == 3) {
defaultCloseOperationString = "EXIT_ON_CLOSE";
} else defaultCloseOperationString = "";
String rootPaneString = (rootPane != null ?
rootPane.toString() : "");
String rootPaneCheckingEnabledString = (rootPaneCheckingEnabled ?
"true" : "false");
return super.paramString() +
",defaultCloseOperation=" + defaultCloseOperationString +
",rootPane=" + rootPaneString +
",rootPaneCheckingEnabled=" + rootPaneCheckingEnabledString;
}
I see no reason why I should be getting this error. Could someone explain this to me?
Methods in an interface must be public.
Also, in your removeInvalidAbstractModifiers() method, you should be using |= to set a flag, rather than +=. The latter will cause problems if the flag is already set (which I realize it won't be if starting from 0, but it's a good habit to get into). Although why you're setting the flag in a method called "remove," I have no idea.
I'd like to be able to read in an XML schema (i.e. xsd) and from that know what are valid attributes, child elements, values as I walk through it.
For example, let's say I have an xsd that this xml will validate against:
<root>
<element-a type="something">
<element-b>blah</element-b>
<element-c>blahblah</element-c>
</element-a>
</root>
I've tinkered with several libraries and I can confidently get <root> as the root element. Beyond that I'm lost.
Given an element I need to know what child elements are required or allowed, attributes, facets, choices, etc. Using the above example I'd want to know that element-a has an attribute type and may have children element-b and element-c...or must have children element-b and element-c...or must have one of each...you get the picture I hope.
I've looked at numerous libraries such as XSOM, Eclipse XSD, Apache XmlSchema and found they're all short on good sample code. My search of the Internet has also been unsuccessful.
Does anyone know of a good example or even a book that demonstrates how to go through an XML schema and find out what would be valid options at a given point in a validated XML document?
clarification
I'm not looking to validate a document, rather I'd like to know the options at a given point to assist in creating or editing a document. If I know "I am here" in a document, I'd like to determing what I can do at that point. "Insert one of element A, B, or C" or "attach attribute 'description'".
This is a good question. Although, it is old, I did not find an acceptable answer. The thing is that the existing libraries I am aware of (XSOM, Apache XmlSchema) are designed as object models. The implementors did not have the intention to provide any utility methods — you should consider implement them yourself using the provided object model.
Let's see how querying context-specific elements can be done by the means of Apache XmlSchema.
You can use their tutorial as a starting point. In addition, Apache CFX framework provides the XmlSchemaUtils class with lots of handy code examples.
First of all, read the XmlSchemaCollection as illustrated by the library's tutorial:
XmlSchemaCollection xmlSchemaCollection = new XmlSchemaCollection();
xmlSchemaCollection.read(inputSource, new ValidationEventHandler());
Now, XML Schema defines two kinds of data types:
Simple types
Complex types
Simple types are represented by the XmlSchemaSimpleType class. Handling them is easy. Read the documentation: https://ws.apache.org/commons/XmlSchema/apidocs/org/apache/ws/commons/schema/XmlSchemaSimpleType.html. But let's see how to handle complex types. Let's start with a simple method:
#Override
public List<QName> getChildElementNames(QName parentElementName) {
XmlSchemaElement element = xmlSchemaCollection.getElementByQName(parentElementName);
XmlSchemaType type = element != null ? element.getSchemaType() : null;
List<QName> result = new LinkedList<>();
if (type instanceof XmlSchemaComplexType) {
addElementNames(result, (XmlSchemaComplexType) type);
}
return result;
}
XmlSchemaComplexType may stand for both real type and for the extension element. Please see the public static QName getBaseType(XmlSchemaComplexType type) method of the XmlSchemaUtils class.
private void addElementNames(List<QName> result, XmlSchemaComplexType type) {
XmlSchemaComplexType baseType = getBaseType(type);
XmlSchemaParticle particle = baseType != null ? baseType.getParticle() : type.getParticle();
addElementNames(result, particle);
}
When you handle XmlSchemaParticle, consider that it can have multiple implementations. See: https://ws.apache.org/commons/XmlSchema/apidocs/org/apache/ws/commons/schema/XmlSchemaParticle.html
private void addElementNames(List<QName> result, XmlSchemaParticle particle) {
if (particle instanceof XmlSchemaAny) {
} else if (particle instanceof XmlSchemaElement) {
} else if (particle instanceof XmlSchemaGroupBase) {
} else if (particle instanceof XmlSchemaGroupRef) {
}
}
The other thing to bear in mind is that elements can be either abstract or concrete. Again, the JavaDocs are the best guidance.
Many of the solutions for validating XML in java use the JAXB API. There's an extensive tutorial available here. The basic recipe for doing what you're looking for with JAXB is as follows:
Obtain or create the XML schema to validate against.
Generate Java classes to bind the XML to using xjc, the JAXB compiler.
Write java code to:
Open the XML content as an input stream.
Create a JAXBContext and Unmarshaller
Pass the input stream to the Unmarshaller's unmarshal method.
The parts of the tutorial you can read for this are:
Hello, world
Unmarshalling XML
I see you have tried Eclipse XSD. Have you tried Eclipse Modeling Framework (EMF)? You can:
Generating an EMF Model using XML Schema (XSD)
Create a dynamic instance from your metamodel (3.1 With the dynamic instance creation tool)
This is for exploring the xsd. You can create the dynamic instance of the root element then you can right click the element and create child element. There you will see what the possible children element and so on.
As for saving the created EMF model to an xml complied xsd: I have to look it up. I think you can use JAXB for that (How to use EMF to read XML file?).
Some refs:
EMF: Eclipse Modeling Framework, 2nd Edition (written by creators)
Eclipse Modeling Framework (EMF)
Discover the Eclipse Modeling Framework (EMF) and Its Dynamic Capabilities
Creating Dynamic EMF Models From XSDs and Loading its Instances From XML as SDOs
This is a fairly complete sample on how to parse an XSD using XSOM:
import java.io.File;
import java.util.Iterator;
import java.util.Vector;
import org.xml.sax.ErrorHandler;
import com.sun.xml.xsom.XSComplexType;
import com.sun.xml.xsom.XSElementDecl;
import com.sun.xml.xsom.XSFacet;
import com.sun.xml.xsom.XSModelGroup;
import com.sun.xml.xsom.XSModelGroupDecl;
import com.sun.xml.xsom.XSParticle;
import com.sun.xml.xsom.XSRestrictionSimpleType;
import com.sun.xml.xsom.XSSchema;
import com.sun.xml.xsom.XSSchemaSet;
import com.sun.xml.xsom.XSSimpleType;
import com.sun.xml.xsom.XSTerm;
import com.sun.xml.xsom.impl.Const;
import com.sun.xml.xsom.parser.XSOMParser;
import com.sun.xml.xsom.util.DomAnnotationParserFactory;
public class XSOMNavigator
{
public static class SimpleTypeRestriction
{
public String[] enumeration = null;
public String maxValue = null;
public String minValue = null;
public String length = null;
public String maxLength = null;
public String minLength = null;
public String[] pattern = null;
public String totalDigits = null;
public String fractionDigits = null;
public String whiteSpace = null;
public String toString()
{
String enumValues = "";
if (enumeration != null)
{
for(String val : enumeration)
{
enumValues += val + ", ";
}
enumValues = enumValues.substring(0, enumValues.lastIndexOf(','));
}
String patternValues = "";
if (pattern != null)
{
for(String val : pattern)
{
patternValues += "(" + val + ")|";
}
patternValues = patternValues.substring(0, patternValues.lastIndexOf('|'));
}
String retval = "";
retval += minValue == null ? "" : "[MinValue = " + minValue + "]\t";
retval += maxValue == null ? "" : "[MaxValue = " + maxValue + "]\t";
retval += minLength == null ? "" : "[MinLength = " + minLength + "]\t";
retval += maxLength == null ? "" : "[MaxLength = " + maxLength + "]\t";
retval += pattern == null ? "" : "[Pattern(s) = " + patternValues + "]\t";
retval += totalDigits == null ? "" : "[TotalDigits = " + totalDigits + "]\t";
retval += fractionDigits == null ? "" : "[FractionDigits = " + fractionDigits + "]\t";
retval += whiteSpace == null ? "" : "[WhiteSpace = " + whiteSpace + "]\t";
retval += length == null ? "" : "[Length = " + length + "]\t";
retval += enumeration == null ? "" : "[Enumeration Values = " + enumValues + "]\t";
return retval;
}
}
private static void initRestrictions(XSSimpleType xsSimpleType, SimpleTypeRestriction simpleTypeRestriction)
{
XSRestrictionSimpleType restriction = xsSimpleType.asRestriction();
if (restriction != null)
{
Vector<String> enumeration = new Vector<String>();
Vector<String> pattern = new Vector<String>();
for (XSFacet facet : restriction.getDeclaredFacets())
{
if (facet.getName().equals(XSFacet.FACET_ENUMERATION))
{
enumeration.add(facet.getValue().value);
}
if (facet.getName().equals(XSFacet.FACET_MAXINCLUSIVE))
{
simpleTypeRestriction.maxValue = facet.getValue().value;
}
if (facet.getName().equals(XSFacet.FACET_MININCLUSIVE))
{
simpleTypeRestriction.minValue = facet.getValue().value;
}
if (facet.getName().equals(XSFacet.FACET_MAXEXCLUSIVE))
{
simpleTypeRestriction.maxValue = String.valueOf(Integer.parseInt(facet.getValue().value) - 1);
}
if (facet.getName().equals(XSFacet.FACET_MINEXCLUSIVE))
{
simpleTypeRestriction.minValue = String.valueOf(Integer.parseInt(facet.getValue().value) + 1);
}
if (facet.getName().equals(XSFacet.FACET_LENGTH))
{
simpleTypeRestriction.length = facet.getValue().value;
}
if (facet.getName().equals(XSFacet.FACET_MAXLENGTH))
{
simpleTypeRestriction.maxLength = facet.getValue().value;
}
if (facet.getName().equals(XSFacet.FACET_MINLENGTH))
{
simpleTypeRestriction.minLength = facet.getValue().value;
}
if (facet.getName().equals(XSFacet.FACET_PATTERN))
{
pattern.add(facet.getValue().value);
}
if (facet.getName().equals(XSFacet.FACET_TOTALDIGITS))
{
simpleTypeRestriction.totalDigits = facet.getValue().value;
}
if (facet.getName().equals(XSFacet.FACET_FRACTIONDIGITS))
{
simpleTypeRestriction.fractionDigits = facet.getValue().value;
}
if (facet.getName().equals(XSFacet.FACET_WHITESPACE))
{
simpleTypeRestriction.whiteSpace = facet.getValue().value;
}
}
if (enumeration.size() > 0)
{
simpleTypeRestriction.enumeration = enumeration.toArray(new String[] {});
}
if (pattern.size() > 0)
{
simpleTypeRestriction.pattern = pattern.toArray(new String[] {});
}
}
}
private static void printParticle(XSParticle particle, String occurs, String absPath, String indent)
{
boolean repeats = particle.isRepeated();
occurs = " MinOccurs = " + particle.getMinOccurs() + ", MaxOccurs = " + particle.getMaxOccurs() + ", Repeats = " + Boolean.toString(repeats);
XSTerm term = particle.getTerm();
if (term.isModelGroup())
{
printGroup(term.asModelGroup(), occurs, absPath, indent);
}
else if(term.isModelGroupDecl())
{
printGroupDecl(term.asModelGroupDecl(), occurs, absPath, indent);
}
else if (term.isElementDecl())
{
printElement(term.asElementDecl(), occurs, absPath, indent);
}
}
private static void printGroup(XSModelGroup modelGroup, String occurs, String absPath, String indent)
{
System.out.println(indent + "[Start of Group " + modelGroup.getCompositor() + occurs + "]" );
for (XSParticle particle : modelGroup.getChildren())
{
printParticle(particle, occurs, absPath, indent + "\t");
}
System.out.println(indent + "[End of Group " + modelGroup.getCompositor() + "]");
}
private static void printGroupDecl(XSModelGroupDecl modelGroupDecl, String occurs, String absPath, String indent)
{
System.out.println(indent + "[GroupDecl " + modelGroupDecl.getName() + occurs + "]");
printGroup(modelGroupDecl.getModelGroup(), occurs, absPath, indent);
}
private static void printComplexType(XSComplexType complexType, String occurs, String absPath, String indent)
{
System.out.println();
XSParticle particle = complexType.getContentType().asParticle();
if (particle != null)
{
printParticle(particle, occurs, absPath, indent);
}
}
private static void printSimpleType(XSSimpleType simpleType, String occurs, String absPath, String indent)
{
SimpleTypeRestriction restriction = new SimpleTypeRestriction();
initRestrictions(simpleType, restriction);
System.out.println(restriction.toString());
}
public static void printElement(XSElementDecl element, String occurs, String absPath, String indent)
{
absPath += "/" + element.getName();
String typeName = element.getType().getBaseType().getName();
if(element.getType().isSimpleType() && element.getType().asSimpleType().isPrimitive())
{
// We have a primitive type - So use that instead
typeName = element.getType().asSimpleType().getPrimitiveType().getName();
}
boolean nillable = element.isNillable();
System.out.print(indent + "[Element " + absPath + " " + occurs + "] of type [" + typeName + "]" + (nillable ? " [nillable] " : ""));
if (element.getType().isComplexType())
{
printComplexType(element.getType().asComplexType(), occurs, absPath, indent);
}
else
{
printSimpleType(element.getType().asSimpleType(), occurs, absPath, indent);
}
}
public static void printNameSpace(XSSchema s, String indent)
{
String nameSpace = s.getTargetNamespace();
// We do not want the default XSD namespaces or a namespace with nothing in it
if(nameSpace == null || Const.schemaNamespace.equals(nameSpace) || s.getElementDecls().isEmpty())
{
return;
}
System.out.println("Target namespace: " + nameSpace);
Iterator<XSElementDecl> jtr = s.iterateElementDecls();
while (jtr.hasNext())
{
XSElementDecl e = (XSElementDecl) jtr.next();
String occurs = "";
String absPath = "";
XSOMNavigator.printElement(e, occurs, absPath,indent);
System.out.println();
}
}
public static void xsomNavigate(File xsdFile)
{
ErrorHandler errorHandler = new ErrorReporter(System.err);
XSSchemaSet schemaSet = null;
XSOMParser parser = new XSOMParser();
try
{
parser.setErrorHandler(errorHandler);
parser.setAnnotationParser(new DomAnnotationParserFactory());
parser.parse(xsdFile);
schemaSet = parser.getResult();
}
catch (Exception exp)
{
exp.printStackTrace(System.out);
}
if(schemaSet != null)
{
// iterate each XSSchema object. XSSchema is a per-namespace schema.
Iterator<XSSchema> itr = schemaSet.iterateSchema();
while (itr.hasNext())
{
XSSchema s = (XSSchema) itr.next();
String indent = "";
printNameSpace(s, indent);
}
}
}
public static void printFile(String fileName)
{
File fileToParse = new File(fileName);
if (fileToParse != null && fileToParse.canRead())
{
xsomNavigate(fileToParse);
}
}
}
And for your Error Reporter use:
import java.io.OutputStream;
import java.io.PrintStream;
import java.text.MessageFormat;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
public class ErrorReporter implements ErrorHandler {
private final PrintStream out;
public ErrorReporter( PrintStream o ) { this.out = o; }
public ErrorReporter( OutputStream o ) { this(new PrintStream(o)); }
public void warning(SAXParseException e) throws SAXException {
print("[Warning]",e);
}
public void error(SAXParseException e) throws SAXException {
print("[Error ]",e);
}
public void fatalError(SAXParseException e) throws SAXException {
print("[Fatal ]",e);
}
private void print( String header, SAXParseException e ) {
out.println(header+' '+e.getMessage());
out.println(MessageFormat.format(" line {0} at {1}",
new Object[]{
Integer.toString(e.getLineNumber()),
e.getSystemId()}));
}
}
For your main use:
public class WDXSOMParser
{
public static void main(String[] args)
{
String fileName = null;
if(args != null && args.length > 0 && args[0] != null)
fileName = args[0];
else
fileName = "C:\\xml\\CollectionComments\\CollectionComment1.07.xsd";
//fileName = "C:\\xml\\PropertyListingContractSaleInfo\\PropertyListingContractSaleInfo.xsd";
//fileName = "C:\\xml\\PropertyPreservation\\PropertyPreservation.xsd";
XSOMNavigator.printFile(fileName);
}
}
It's agood bit of work depending on how compex your xsd is but basically.
if you had
<Document>
<Header/>
<Body/>
<Document>
And you wanted to find out where were the alowable children of header you'd (taking account of namespaces)
Xpath would have you look for '/element[name="Document"]/element[name="Header"]'
After that it depends on how much you want to do. You might find it easier to write or find something that loads an xsd into a DOM type structure.
Course you are going to possibly find all sorts of things under that elment in xsd, choice, sequence, any, attributes, complexType, SimpleContent, annotation.
Loads of time consuming fun.
Have a look at this.
How to parse schema using XOM Parser.
Also, here is the project home for XOM
this is my code :
public static List populate(ResultSet rs, Class clazz) throws Exception {
ResultSetMetaData metaData = rs.getMetaData();
int colCount = metaData.getColumnCount();
List ret = new ArrayList();
Field[] fields = clazz.getDeclaredFields();
while (rs.next()) {
Object newInstance = clazz.newInstance();
for (int i = 1; i <= colCount; i++) {
try {
Object value = rs.getObject(i);
for (int j = 0; j < fields.length; j++) {
Field f = fields[j];
if (f.getName().replaceAll("_", "").equalsIgnoreCase(
metaData.getColumnName(i).replaceAll("_", ""))) {
BeanUtils.copyProperty(newInstance, f.getName(),
value);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
ret.add(newInstance);
}
rs.close();
return ret;
}
and this is the method to call it :
public List getLastAddress(String terminal_id, String last_2) throws Exception {
String sql ="SELECT a.adress_reality from accounts_location_"+last_2+" AS a WHERE a.terminal_id = '"
+terminal_id+"' ORDER BY a.time_stamp DESC limit 1";
System.out.println(sql);
ResultSet rs = getDr().getSt().executeQuery(sql);
return populate(rs, Class.forName("hdt.ChineseAddressBean"));
and then :
List cn_address=sd.getLastAddress(toNomber,last_2);
System.out.println(cn_address.get(0));
but it show :
hdt.ChineseAddressBean#f0eed6
so How to get the current string from cn_address.get(0),
thanks
this is my ChineseAddressBean.java:
package hdt;
public class ChineseAddressBean {
String adress_reality = "";
public String getAdress_reality() {
return adress_reality;
}
public void setAdress_reality(String adress_reality) {
this.adress_reality = adress_reality;
}
}
updated1:
when i use this , it show error :
updated2:
this is the error :
Object address = cn_address.get(0);
ChineseAddressBean chineseaddressbean = (ChineseAddressBean)address;
System.out.println(chineseaddressbean.getAdress_reality());
The above lines is what you need to do to achieve what you want.Please let me know if its working.
Meybe you need to make method toString () in Your class instance.
Apparently you are getting a list of objects of class "ChineseAddressBean" in cn_address. Right?
Then if you do
List cn_address=sd.getLastAddress(toNomber,last_2);
System.out.println(cn_address.get(0));
It will take the first element in the list and print it. To print it, it will try to convert it to String by calling toString method of the object. So if you override toString method in class "ChineseAddressBean" and return whatever you want to print, it will do the trick
you dont have a toString() method in your bean.
public String toString() {
return adress_reality;
}
Missed in your example that you need to cast the objects retrieved from your list to the appropriate type.
So:
System.out.println((ChineseAddressBean)cn_address.get(0));
Returning List you access Object (not ChineseAddressBean). Also when you print it you call default toString() method which returns class name followed by hash code.
You have to return List<ChineseAddressBean> or cast the result to ChineseAddressBean (which you are doing wrong).
Try this one:
System.out.println(((ChineseAddressBean)(cn_address.get(0))).getAdress_reality());
You can also write toString() method for ChineseAddressBean which returns address string and then you dont have to call getAdress_reality().
cn_address.get(0) returns an object, you should convert it to a string