Search code examples
javajaxbxsdobject-graph

How can I represent a Hierarchy of Objects in an XML Schema in a way that is suitable for JAXB and Java


I have a data model that represents a taxonomy. The taxonomy is a hierarchy of categories, such as

Food
 +- Pasta
     +- Spaghetti

I would like to represent this as

<taxonomy>
  <category id="cat001" name="Food"/>

  <category id="cat002" name="Pasta">
    <parentCategory>
      <category ref="cat001"/>
    </parentCategory>
  </category>

  <category id="cat003" name="Spaghetti">
    <parentCategory>
      <category ref="cat002"/>
    </parentCategory>
  </category>
</taxonomy>

What is the best way to represent this in an XML schema (XSD)?

Also, how can I ensure that when using JAXB, I can get something like

class Category {
  String name;
  Category parentCategory;
}

Further, what if my taxonomy is not a strict tree, but a graph, where there may be more than one parent relationship, such that Spaghetti comes under Pasta as well as Noodles

<taxonomy>
  <category id="cat001" name="Food"/>

  <category id="cat002" name="Pasta">
    <parentCategories>
      <category ref="cat001"/>
    </parentCategories>
  </category>

  <category id="cat003" name="Noodles">
    <parentCategories>
      <category ref="cat001"/>
    </parentCategories>
  </category>

  <category id="cat004" name="Spaghetti">
    <parentCategories>
      <category ref="cat002"/> <!-- Pasta -->
      <category ref="cat003"/> <!-- Noodles -->
    </parentCategory>
  </category>
</taxonomy>

and with JAXB, I would want to then generate something like

class Category {
  String name;
  List<Category> parentCategories;
}

Note, the Java code is simplified for illustration purposes only. With JAXB code generation, I don't mind having a container object, such as parentCategory having a category property


Solution

  • Recommendation - Start From Java Objects

    For your use case I would recommend starting with the object model you want and then applying JAXB annotations to map it to the desired XML representation. The following example should help:

    XML Schema

    If you then need an XML schema you can generate one from your JAXB model.

    import java.io.IOException;
    import javax.xml.bind.*;
    import javax.xml.transform.Result;
    import javax.xml.transform.stream.StreamResult;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            JAXBContext jc = JAXBContext.newInstance(SpThread.class);
    
            jc.generateSchema(new SchemaOutputResolver() {
    
                @Override
                public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
                    StreamResult result = new StreamResult(System.out);
                    result.setSystemId(suggestedFileName);
                    return result;
                }
    
            });
        }
    
    }
    

    Shared References

    You can use @XmlID and @XmlIDREF to create key based references within the XML document.