Entity / relationship pattern

Background

One of the modeling patterns supported by PageSeeder will be familiar to anyone with knowledge of Entity Relationship Diagrams (ERDs). As a long time tool for relational database developers and analysts, the screen below may help to illustrate how a PageSeeder document type can be thought of as the equivalent of a relational table.

ps-doc-type-table.png

Similarly, what appears as a row in the view above, appears more like a record in the screenshot below. In the screen below, the value of a column in the table view looks like a field in the record view.

Finally, if the name of the director was an xref to a biographical document, this would look like a join.

 

ps-doc-type-row.png

 

Based on these fundamental concepts, this article will look at an example of a book with a publisher and multiple authors in more detail. An Entity-relationship  diagram such as the one below is a useful tool for modelling. When expressing the diagram, make each type of content an entity then label certain fields and each relationship with the appropriate cardinality (e.g. N..1, N..M).

book-author-publisher.svg

PageSeeder concepts

Cross-references (XRefs)

In PageSeeder the rich references between documents are called XRefs, they have many properties, the ones that are relevant to this example are:

  • link type: is a processing instruction that tells PageSeeder when exporting what it should do with the linked content whether it is simple a reference or whether the content should be included;
  • reverse link: whether we want the reference to be visible to the document being referenced.

The model could be used to generate detail to be included in the front matter of a book so in that case we'd want the links between the book and the other documents to be embed, so that when the document was processed that information could be included.

We'd also want the reverse links to be true between the book and the author to be available so from the Author document we could easily see all the books they'd authored. 

Document types

PageSeeder lets you define specific document types that can capture very specifically the object you're trying to describe.  A PageSeeder document is comprised of:

  • sections: a section within PageSeeder document is used to organise content, you can lock a section or limit the fragment types that are available;
  • fragments: the basic content unit for PageSeeder, fragments contain all of the content. They can be of different types, ranging from limiting the content to a fixed set of properties or allowing for rich content to be added. A history is kept for each fragment within a document.   

A document type is a specific combination of sections, fragment types and fragments that is sympathetic to the data that is being captured.

Book

The book document properties:

  • Title: text
  • ISBN: text, with validated format
  • Author(s): XRef to one or more Author documents
  • Publisher: single XRef to publisher document

Publisher

The Publisher document properties:

  • Name: Text
  • Address: Text 

Author

The Author document property:

  • Name: Text

PSML representation

In book ER model could be implemented in PSML using the following rules:

  • A document type for each entity.
  • A <property> for each field. To improve user productivity and quality of data, consider creating a custom editor PSMLPropertiesConfig for each data set.
  • Create a <property> of @datatype="xref" in order to express each of the following relationships:
    • 1 to 1,
    • 0..1 to 0..1
  • Create a <property> of @datatype="xref" at the N end of each following relationship. It is possible to use a @count="n" or an <xref-fragment> from the 1 end of the relationship but if N is a large number this makes editing cumbersome.
    • 1 to N,
    • 0..1 to N.
  • Create an <xref-fragment> for each following relationship. To reduce the number of xrefs being edited this is usually done from the end for which N or M is largest.
    • N to M,
    • 0..N to 0..M.

Remember that XRefs only need to be created at one end of the relationship, with the reverse XRefs being created automatically.

Below are examples of the resulting PSML documents, along with some advice on additional configuration options.

Book

<document level="portable" type="book">
  <section id="details">
    <properties-fragment id="1">
      <property name="title"
               title="Title"
               value="My story"/>
      <property name="isbn"
               title="ISBN"
               value="0864412345"/>
      <property name="category"
               title="Category"
               value="Fiction"/>    
 
      <property name="publisher"
            datatype="xref"
               title="Publisher">
        <xref type="none"
              frag="default" 
              href="../../publishers/00/publisher-001.psml">
                             XYZ Books</xref>
      </property>
   </properties-fragment>
 </section>
 <section id="authors" title="Authors">
   <xref-fragment id="2">
     <blockxref type="none"
                frag="default"
                href="../../authors/00/author-001.psml">
                             John Jones</blockxref>
     <blockxref type="none"
                frag="default"
                href="../../authors/00/author-002.psml">
                             Jane Black</blockxref>
    </xref-fragment>
  </section>
</document>

Cardinality

PageSeeder is very flexible in how the document types are constructed, but once they are set up they can enforce the model.

The 1..N relationship between publishers and books is enforced by expressing the  relationship as a single reference from the book to the publisher. This way the publisher can be referred to by many books and a book can only refer to one publisher.

File naming

Where multiple files need to be created, the document-config.xml can be used to automatically spawn files with unique, sequentially numbered filenames in a designated folder.

For example, to populate a folder called "books" with files that start with the name:

/books/00/book-001.psml

this code could be added to the document config:

<creation>
  <title>Book</title>
  <folder context="/books" path="{0P1000}" />
  <filename value="book-{NNN}" editable="false"/>
  <document title="Book {N} {$ui.title}" docid="B{0000N}" />
</creation>

To support multiple collections of the same entity, use a * wildcard in the @context attribute of the <folder> element. For example @context="/libraries/*/books" would create books under

/libraries/mytown/books/00/book-001.psml

or

/libraries/yourtown/books/00/book-001.psml

Note

Be aware of potential naming clashes when using PageSeeder to generate names at the same time as creating  documents externally and then uploading them to PageSeeder. Use a prefix  (e.g. book-x001.psml) or some other technique to prevent confusion.

XRefs

 To autosuggest the correct document type in an <xref-fragment>, edit the editor-config.xml similar to the following example:

<editor-configs>
  <editor-config name="PSMLXRefs">
    <xref-config fragmenttype="default">
      <xref type="none"/>
      <target documenttype="author" />
    </xref-config>
  </editor-config>
</editor-configs>

Where the target document type is in multiple collections, the autosuggest can be further restricted by adding <autosuggest> with @folder under <xref-config>. For example:

<editor-configs>
  <editor-config name="PSMLXRefs">
    <xref-config fragmenttype="default">
      <xref type="none"/>
      <target documenttype="author" />
      <autosuggest folder="libraries/*" />
    </xref-config>
  </editor-config>
</editor-configs>

In this example, the * will be replaced with the context of the current document. For example:

libraries/mytown

Author

<document level="portable" type="author">
   <section id="details">
      <properties-fragment id="1">
         <property name="author"
                  title="Author"
                  value="John Jones"/>
     </properties-fragment>
  </section>
</document>

Publisher

<document level="portable" type="publisher"> 
   <section id="details"> 
      <properties-fragment id="1"> 
        <property name="publisher"
                 title="Publisher"
                 value="XYZ Books"/>
        <property name="address"
                 title="Address"
                 value="P.O. Box 123, My City"/>
     </properties-fragment>
   </section> 
</document>

 

Created on , last edited on