In Java, how do I parse an xml schema (xsd) to learn what's valid at a given element?

前端 未结 6 1945
感动是毒
感动是毒 2021-02-08 23:01

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

6条回答
  •  名媛妹妹
    2021-02-08 23:31

    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 enumeration = new Vector();
                Vector pattern     = new Vector();
    
                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 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 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);
        }
    }
    

提交回复
热议问题