如何使用Apache XMLBeans从Xsd-Schema读取Xsd-Annotations?

时间:2018-01-10 21:56:25

标签: java xsd xmlbeans

我使用Apache XMLBeans读取了一个xsd-schema文件,从根元素开始迭代所有 SchemaProperties 。 在每个SchemaProperty我正在寻找一个注释: schemaProperty.getType()。getAnnotation(),但我找不到任何注释。 (以下java代码)

我检查了以下xsd文件:

xsd结构图:

figure of xsd structure

Xsd源代码:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="ExterneDaten" type="ExterneDaten">
    <xs:annotation>
        <xs:documentation>annotation for ExterneDaten</xs:documentation>
    </xs:annotation>
</xs:element>
<xs:complexType name="ExterneDaten">
    <xs:annotation>
        <xs:documentation>annotation for Type ExterneDaten</xs:documentation>
    </xs:annotation>
    <xs:sequence>
        <xs:element name="value1" type="xs:string">
            <xs:annotation>
                <xs:documentation>annotation for value1</xs:documentation>
            </xs:annotation>
        </xs:element>
    </xs:sequence>
    <xs:attribute name="isTest" type="xs:boolean">
        <xs:annotation>
            <xs:documentation>annotation for boolean attribute isTest</xs:documentation>
        </xs:annotation>
    </xs:attribute>
</xs:complexType>

我用我的函数检查xsd: MyXsdReader.readAllAnnotationsFromXsd(String schema);

这是java代码:

public class MyXsdReader
{

    public static void readAllAnnotationsFromXsd(String newSchema)
    {
        try
        {
            SchemaTypeLoader loader = XmlBeans.typeLoaderForClassLoader(SchemaDocument.class.getClassLoader());

            XmlObject[] xmlObjects = new XmlObject[1];
            XmlOptions options = new XmlOptions();
            options.setLoadLineNumbers().setLoadMessageDigest().setCharacterEncoding("utf-8");
            options.setCompileDownloadUrls();
            xmlObjects[0] = loader.parse(newSchema, null, options);
            SchemaTypeSystem sts = XmlBeans.compileXsd(xmlObjects, XmlBeans.getBuiltinTypeSystem(), options);
            readXsdRootElement(sts);

        }
        catch (Exception e)
        {
            System.out.println("makeXsdListRootEle(): Excpetion: " + e.getMessage());
        }
    }

    private static void readXsdRootElement(SchemaTypeSystem sts)
    {
        SchemaGlobalElement[] globals = sts.globalElements();
        if (globals != null && globals.length == 1)
        {
            SchemaGlobalElement sge = globals[0];
            SchemaType st = sge.getType();
            SchemaProperty[] properties = st.getProperties();
            for (int k = 0; k < properties.length; k++)
            {
            SchemaProperty property = properties[k];
            checkAnnotation(property);
            if (property.isAttribute() == false)
            {
                readXsdProperty(property);
            }
            }
        }
    }

    private static void readXsdProperty(SchemaProperty property)
    {
        SchemaProperty[] properties = property.getType().getProperties();
        for (SchemaProperty schemaProperty : properties)
        {
            checkAnnotation(schemaProperty);
            readXsdProperty(schemaProperty);
        }
    }

    private static void checkAnnotation(SchemaProperty schemaProperty)
    {
        SchemaAnnotation annotation = schemaProperty.getType().getAnnotation();
        if (annotation != null)
        {
            System.out.println(annotation.toString());
        }
    }
}

我该怎么做才能读取xsd中的注释?

2 个答案:

答案 0 :(得分:1)

我有相同的要求,并且能够解析XSD中的Annotations,如下所示。

说XSD如下:-

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="ExterneDaten" type="ExterneDaten">
    <xs:annotation>
        <xs:documentation>annotation for ExterneDaten</xs:documentation>
    </xs:annotation>
</xs:element>
<xs:complexType name="ExterneDaten">
    <xs:annotation>
        <xs:documentation>annotation for Type ExterneDaten</xs:documentation>
    </xs:annotation>
    <xs:sequence>
        <xs:element name="value1" type="xs:string">
            <xs:annotation>
                <xs:documentation>annotation for value1</xs:documentation>
            </xs:annotation>
        </xs:element>
    </xs:sequence>
    <xs:attribute name="isTest" type="xs:boolean">
        <xs:annotation>
            <xs:documentation>annotation for boolean attribute isTest</xs:documentation>
        </xs:annotation>
    </xs:attribute>
</xs:complexType>

现在,我们必须创建一个自定义注释解析器,如下所示:-

public class XSDAnnotaionParser extends AnnotationParser {

    private StringBuilder documentation = new StringBuilder();

    @Override
    public ContentHandler getContentHandler(AnnotationContext context, String parentElementName, ErrorHandler handler,
            EntityResolver resolver) {
        return new ContentHandler() {
            private boolean parsingDocumentation = false;

            @Override
            public void characters(char[] ch, int start, int length) throws SAXException {
                if (parsingDocumentation) {
                    documentation.append(ch, start, length);
                }
            }

            @Override
            public void endElement(String uri, String localName, String name) throws SAXException {
                //say you want to parse the text in "documentaion" tag in your xsd....this is where we scpecify the tag
                if (localName.equals("documentation")) {
                    parsingDocumentation = false;
                }
            }

            @Override
            public void startElement(String uri, String localName, String name, Attributes atts) throws SAXException {
                if (localName.equals("documentation")) {
                    parsingDocumentation = true;
                }
            }

            @Override
            public void setDocumentLocator(Locator locator) {
                // TODO Auto-generated method stub

            }

            @Override
            public void startDocument() throws SAXException {
                // TODO Auto-generated method stub

            }

            @Override
            public void endDocument() throws SAXException {
                // TODO Auto-generated method stub

            }

            @Override
            public void startPrefixMapping(String prefix, String uri) throws SAXException {
                // TODO Auto-generated method stub

            }

            @Override
            public void endPrefixMapping(String prefix) throws SAXException {
                // TODO Auto-generated method stub

            }

            @Override
            public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
                // TODO Auto-generated method stub

            }

            @Override
            public void processingInstruction(String target, String data) throws SAXException {
                // TODO Auto-generated method stub

            }

            @Override
            public void skippedEntity(String name) throws SAXException {
                // TODO Auto-generated method stub

            }
        };
    }

    @Override
    public Object getResult(Object existing) {
        return documentation.toString().trim();
    }
}

现在,我们为上面创建的自定义注释解析器创建一个工厂类,如下所示:-

class AnnotationFactory implements AnnotationParserFactory {
    @Override
    public AnnotationParser create() {
        return new XSDAnnotaionParser();
    }
}

现在,我们将自定义注释解析器添加到XSOMParser中,用于解析XSD,如下所示:-

XSOMParser parser = new XSOMParser();
parser.setAnnotationParser(new AnnotationFactory());
try {
    parser.parse(xml);
} catch (SAXException ex) {
    throw new SchemaException(ex);
}

要解析文档标签,我们可以使用以下代码:-

XSSchemaSet schemaSet = null;
        try {
            schemaSet = parser.getResult();
        } catch (SAXException ex) {
            throw new SchemaException(ex);
        }

        Iterator<XSElementDecl> iterator = schemaSet.iterateElementDecls();
    while (iterator.hasNext()) {
        XSElementDecl elementDecl= (XSElementDecl) iterator.next();
        XSComplexType eleCompDecl= elementDecl.getType().asComplexType();
        if (eleCompDecl!= null) {
            //we get the annotation here
            XSAnnotation annotaion = eleCompDecl.getAnnotation();
            //this will print the tezxt inside documentaion tag
            System.out.println(annotaion.getAnnotation());
        }
    }

用于读取xsd属性内部注释的代码如下:-

            Collection<? extends XSAttributeUse> attributes= eleCompDecl.getAttributeUses();

            Iterator<? extends XSAttributeUse> iterator = attributes.iterator();
            while(attributes.hasNext()) {

                XSAttributeUse next = attributes.next();
                XSAttributeDecl attributeDecl = next.getDecl(); 
                String desc = null;
                if(attributeDecl != null) {
                    try {
                        desc = (String)attributeDecl.getAnnotation().getAnnotation();
                        System.out.println("the documentaion for the attribute is "+desc)
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }

答案 1 :(得分:0)

我遇到了同样的问题,并使用Apache xmlbeans为我解决了以下问题。该示例基本上是Groovy代码,但应易于转移到Java。

void parseDocumentations(File xsdFile) {
    // load the xsd
    XmlObject object = XmlObject.Factory.parse(xsdFile)
    List<XmlObject> objectList = []
    objectList.add(object)
    // parse the xsd content to a object tree
    SchemaTypeSystem sts = XmlBeans.compileXsd((XmlObject[])objectList.toArray(), XmlBeans.getBuiltinTypeSystem(), null)
    def globalTypes = sts.globalTypes()
    // iterate over the defined types in the xsd
    for (SchemaType type: globalTypes) {
        def annotation = type.getAnnotation()
        if (annotation!=null) {
            // get the sub xml nodes of the annotation node
            def userInfos = annotation.userInformation
            for (XmlObject userInfo: userInfos ) {
                if (userInfo.getDomNode().localName=='documentation') {
                    // extract the text from documentation node
                    def documentationTxt = userInfo.getDomNode().getFirstChild().getNodeValue()
                    println documentationTxt
                }
            }
        }

    }
}