Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
195 views
in Technique[技术] by (71.8m points)

java - XMLBeans: Get annotation of a nested element

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...