XMLBeans: Get annotation of a nested element

ε祈祈猫儿з 提交于 2019-12-12 03:38:58

问题


I'm trying to get the annotation of an element that is declared within a xs:complexType in my XSD. Such an element is of type SchemaPreperty. However, unlike with SchemaGlobalElement and SchemaType, there is no SchemaProperty.getAnnotation() that I can use.

This is the XSD. I need to access the documentation of element number.

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="test" type="my-test-type" />

    <xs:complexType name="my-test-type">
        <xs:sequence>
            <xs:element name="number" "xs:int">
                <xs:annotation>
                    <xs:documentation>This is the documentation I need.</xs:documentation>
                </xs:annotation>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

How do I do this? It doesn't seem... possible.


回答1:


So I found the answer in the XMLBeans FAQ. Here's the link

I'm pasting the FAQ's code, since answers that just contain links are frowned upon. You can pretty much figure out how to adapt it to your own needs from this example:

public static void someMethod() {
    SchemaType t = XmlBeans.getContextTypeLoader().findType(new QName("http://test", "T"));
    SchemaProperty[] schemaProperties = t.getProperties();
    for (int i = 0; i < schemaProperties.length; i++)
        printPropertyInfo(schemaProperties[i]);

    System.out.println();

    if (t.getContentType() == SchemaType.ELEMENT_CONTENT ||
            t.getContentType() == SchemaType.MIXED_CONTENT)
    {
        SchemaParticle topParticle = t.getContentModel();
        // topParticle is non-null if we checked the content
        navigateParticle(topParticle);
    }
}

public static void navigateParticle(SchemaParticle p)
{
    switch (p.getParticleType())
    {
    case SchemaParticle.ALL:
    case SchemaParticle.CHOICE:
    case SchemaParticle.SEQUENCE:
        // These are "container" particles, so iterate over their children
        SchemaParticle[] children = p.getParticleChildren();
        for (int i = 0; i < children.length; i++)
            navigateParticle(children[i]);
        break;
    case SchemaParticle.ELEMENT:
        printElementInfo((SchemaLocalElement) p);
        break;
    default:
        // There can also be "wildcards" corresponding to <xs:any> elements in the Schema
    }
}

public static void printPropertyInfo(SchemaProperty p)
{
    System.out.println("Property name=\"" + p.getName() + "\", type=\"" + p.getType().getName()
        + "\", maxOccurs=\"" +
        (p.getMaxOccurs() != null ? p.getMaxOccurs().toString() : "unbounded") + "\"");
}

public static void printElementInfo(SchemaLocalElement e)
{
    System.out.println("Element name=\"" + e.getName() + "\", type=\"" + e.getType().getName()
        + "\", maxOccurs=\"" +
        (e.getMaxOccurs() != null ? e.getMaxOccurs().toString() : "unbounded") + "\"");
    SchemaAnnotation annotation = e.getAnnotation();
    if (annotation != null)
    {
        SchemaAnnotation.Attribute[] att = annotation.getAttributes();
        if (att != null && att.length > 0)
            System.out.println("  Annotation: " + att[0].getName() + "=\"" +
                att[0].getValue() + "\"");
    }
}

As for attributes, the FAQ doesn't even mention them, but they are accessed differently. This gave me a huge headache, because I was trying to figure out how to access an attribute's annotation similarly to the code above. Accessing an attribute's annotations is pretty easy and straightforward though.

Here's my current method for doing so:

public String getAttributeAnnotation(SchemaType t, String attributeLocalName) {
    if (null != t) {
        SchemaAttributeModel attrModel = t.getAttributeModel();
        if (null != attrModel) {
            SchemaLocalAttribute[] attributes = t.getAttributeModel().getAttributes();
            if (attributes.length > 0) {
                SchemaLocalAttribute attr = Arrays.stream(attributes)
                        .filter(a -> a.getName().getLocalPart().equals(attributeLocalName))
                        .findFirst().orElse(null);
                if (null != attr) {
                    String annotationDoc = getAnnotationDocumentation(attr.getAnnotation());
                    return annotationDoc;
                }
            }
        }
    }

    return null;
}

Here's my getAnnotationDocumentation() (which can be improved upon!). You can use it for retrieving the xs:documentation inside an xs:annotation for both elements and attributes.

public static String getAnnotationDocumentation(SchemaAnnotation an) {
    if (null != an) {
        StringBuilder sb = new StringBuilder();
        XmlObject[] userInformation = an.getUserInformation();
        if (null != userInformation & userInformation.length > 0) {
            for (XmlObject obj : userInformation) {
                Node docInfo = obj.getDomNode();
                NodeList list = docInfo.getChildNodes();
                for (int i = 0; i < list.getLength(); i++) {
                    Node c = list.item(i);
                    if (c.getNodeType() == Node.TEXT_NODE) {
                        String str = c.getNodeValue();
                        sb.append(str.trim());
                        break;
                    }
                }
            }
        }
        return sb.toString();
    }
    return null;
}



回答2:


I had the same requirement and , if you are looking for a different approach, you may refer here at my answer :How to read Xsd-Annotations from Xsd-Schema using Apache XMLBeans?



来源:https://stackoverflow.com/questions/42965146/xmlbeans-get-annotation-of-a-nested-element

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!