From e63d82d9824de7316ca618424196a5a0d3ab67d1 Mon Sep 17 00:00:00 2001 From: Carsten Englert Date: Sat, 5 Sep 2015 01:02:07 +1200 Subject: [PATCH] create XML Schema, introduce unique namespaces --- scitos.ais/schema/ais-v1.0.xsd | 113 ++++++++++++++++++ .../ais/core/ModelParseServiceImpl.java | 32 +++-- .../org/hmx/scitos/ais/stylesheet.xsl | 62 +++++----- 3 files changed, 164 insertions(+), 43 deletions(-) create mode 100644 scitos.ais/schema/ais-v1.0.xsd diff --git a/scitos.ais/schema/ais-v1.0.xsd b/scitos.ais/schema/ais-v1.0.xsd new file mode 100644 index 0000000..65c4309 --- /dev/null +++ b/scitos.ais/schema/ais-v1.0.xsd @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/scitos.ais/scitos.ais.core/src/main/java/org/hmx/scitos/ais/core/ModelParseServiceImpl.java b/scitos.ais/scitos.ais.core/src/main/java/org/hmx/scitos/ais/core/ModelParseServiceImpl.java index 34ede30..07c6dd3 100644 --- a/scitos.ais/scitos.ais.core/src/main/java/org/hmx/scitos/ais/core/ModelParseServiceImpl.java +++ b/scitos.ais/scitos.ais.core/src/main/java/org/hmx/scitos/ais/core/ModelParseServiceImpl.java @@ -60,6 +60,11 @@ public class ModelParseServiceImpl implements IModelParseService { /* * Collection of the XML tags and attributes for representing an AIS module's project in its persisted form. */ + private static final String NAMESPACE = "http://www.hermeneutix.org/schema/ais/1.0"; + private static final String SCHEMA_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance"; + private static final String SCHEMA_REF_ATTRIBUTE = "xsi:schemaLocation"; + private static final String SCHEMA_LOCATION = + "https://raw.githubusercontent.com/scientific-tool-set/scitos/master/scitos.ais/schema/ais-v1.0.xsd"; private static final String TAG_ROOT = "AisProject"; private static final String TAG_CATEGORY_ROOT = "Categories"; private static final String TAG_CATEGORY = "Category"; @@ -97,11 +102,14 @@ public Document parseXmlFromModel(final IModel model, final List openViewE final AisProject project = (AisProject) model; try { final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); - doc.appendChild(doc.createElement(ModelParseServiceImpl.TAG_ROOT)); + doc.appendChild(doc.createElementNS(ModelParseServiceImpl.NAMESPACE, ModelParseServiceImpl.TAG_ROOT)); + // add schema reference + doc.getDocumentElement().setAttributeNS(ModelParseServiceImpl.SCHEMA_NAMESPACE, ModelParseServiceImpl.SCHEMA_REF_ATTRIBUTE, + ModelParseServiceImpl.NAMESPACE + ' ' + ModelParseServiceImpl.SCHEMA_LOCATION); // include categories used doc.getDocumentElement().appendChild(this.parseXmlFromDetailCategories(doc, project)); // include scored interviews - final Element interviewRoot = doc.createElement(ModelParseServiceImpl.TAG_INTERVIEW_ROOT); + final Element interviewRoot = doc.createElementNS(ModelParseServiceImpl.NAMESPACE, ModelParseServiceImpl.TAG_INTERVIEW_ROOT); final List interviews = new ArrayList(project.getInterviews()); // add interviews in sorted order - just for a user who opens the file in a text editor Collections.sort(interviews); @@ -193,7 +201,7 @@ Element parseXmlFromDetailCategories(final Document doc, final IDetailCategoryPr final MutableDetailCategoryModel categoryFamily = new MutableDetailCategoryModel(); categoryFamily.addAll(categoryProvider.provide()); // create single element to hold all categories - final Element categoryRootElement = doc.createElement(ModelParseServiceImpl.TAG_CATEGORY_ROOT); + final Element categoryRootElement = doc.createElementNS(ModelParseServiceImpl.NAMESPACE, ModelParseServiceImpl.TAG_CATEGORY_ROOT); // add only the root categories, which in turn add their own children recursively for (final DetailCategory singleCategoryRoot : categoryFamily.getRootCategories()) { categoryRootElement.appendChild(this.parseXmlFromDetailCategoryTree(doc, singleCategoryRoot, categoryFamily)); @@ -216,7 +224,7 @@ Element parseXmlFromDetailCategories(final Document doc, final IDetailCategoryPr */ private Element parseXmlFromDetailCategoryTree(final Document doc, final DetailCategory target, final MutableDetailCategoryModel categoryFamily) { // create category element and set its attributes - final Element categoryElement = doc.createElement(ModelParseServiceImpl.TAG_CATEGORY); + final Element categoryElement = doc.createElementNS(ModelParseServiceImpl.NAMESPACE, ModelParseServiceImpl.TAG_CATEGORY); categoryElement.setAttribute(ModelParseServiceImpl.ATTR_CATEGORY_CODE, target.getCode()); categoryElement.setAttribute(ModelParseServiceImpl.ATTR_CATEGORY_NAME, target.getName()); final Color color = target.getColor(); @@ -328,7 +336,7 @@ private List parseDetailCategoriesFromXmlRecursively(final NodeL */ private Element parseXmlFromInterview(final Document doc, final Interview target) { // create interview element and set its attributes - final Element interviewElement = doc.createElement(ModelParseServiceImpl.TAG_INTERVIEW); + final Element interviewElement = doc.createElementNS(ModelParseServiceImpl.NAMESPACE, ModelParseServiceImpl.TAG_INTERVIEW); interviewElement.setAttribute(ModelParseServiceImpl.ATTR_INTERVIEW_PARTICIPANT, target.getParticipantId()); interviewElement.setAttribute(ModelParseServiceImpl.ATTR_INTERVIEW_INDEX, String.valueOf(target.getIndex())); // include the scored text @@ -349,7 +357,7 @@ private Element parseXmlFromInterview(final Document doc, final Interview target */ private Element parseXmlFromInterviewParagraph(final Document doc, final TextToken paragraphStart) { // create paragraph wrapping element - final Element paragraphElement = doc.createElement(ModelParseServiceImpl.TAG_INTERVIEW_PARAGRAPH); + final Element paragraphElement = doc.createElementNS(ModelParseServiceImpl.NAMESPACE, ModelParseServiceImpl.TAG_INTERVIEW_PARAGRAPH); // iterate through tokens TextToken currentToken = paragraphStart; do { @@ -379,7 +387,7 @@ private Element parseXmlFromInterviewParagraph(final Document doc, final TextTok */ private Entry parseXmlFromTokenRange(final Document doc, final TextToken rangeStart) { // create range wrapping element and set assigned category by its code - final Element detailElement = doc.createElement(ModelParseServiceImpl.TAG_INTERVIEW_DETAIL); + final Element detailElement = doc.createElementNS(ModelParseServiceImpl.NAMESPACE, ModelParseServiceImpl.TAG_INTERVIEW_DETAIL); final DetailCategory category = rangeStart.getDetail(); // ranges inside ranges can have no category assigned if (category != null) { @@ -422,7 +430,7 @@ private Entry parseXmlFromTokenRange(final Document doc, fin */ private Element parseXmlFromTokenText(final Document doc, final TextToken target) { // after converting all the category info into wrapping xml structure, the node for the token contains only its text - final Element tokenElement = doc.createElement(ModelParseServiceImpl.TAG_INTERVIEW_TOKEN); + final Element tokenElement = doc.createElementNS(ModelParseServiceImpl.NAMESPACE, ModelParseServiceImpl.TAG_INTERVIEW_TOKEN); tokenElement.appendChild(doc.createTextNode(target.getText())); return tokenElement; } @@ -528,18 +536,18 @@ private TextToken parseTextParagraphFromXml(final Element paragraphElement, fina * @return created {@value #TAG_VIEWS} node */ private Element parseXmlFromOpenViewElements(final Document doc, final List openViewElements) { - final Element viewElementWrapper = doc.createElement(ModelParseServiceImpl.TAG_VIEWS); + final Element viewElementWrapper = doc.createElementNS(ModelParseServiceImpl.NAMESPACE, ModelParseServiceImpl.TAG_VIEWS); for (final Object viewElement : openViewElements) { final Element view; if (viewElement instanceof Interview) { - view = doc.createElement(ModelParseServiceImpl.TAG_VIEWS_INTERVIEW); + view = doc.createElementNS(ModelParseServiceImpl.NAMESPACE, ModelParseServiceImpl.TAG_VIEWS_INTERVIEW); view.setAttribute(ModelParseServiceImpl.ATTR_VIEWS_INTERVIEW_PARTICIPANT, ((Interview) viewElement).getParticipantId()); view.setAttribute(ModelParseServiceImpl.ATTR_VIEWS_INTERVIEW_INDEX, String.valueOf(((Interview) viewElement).getIndex())); } else if (viewElement instanceof String) { - view = doc.createElement(ModelParseServiceImpl.TAG_VIEWS_GROUP); + view = doc.createElementNS(ModelParseServiceImpl.NAMESPACE, ModelParseServiceImpl.TAG_VIEWS_GROUP); view.setAttribute(ModelParseServiceImpl.ATTR_VIEWS_GROUP_NAME, (String) viewElement); } else { - view = doc.createElement(ModelParseServiceImpl.TAG_VIEWS_PROJECT); + view = doc.createElementNS(ModelParseServiceImpl.NAMESPACE, ModelParseServiceImpl.TAG_VIEWS_PROJECT); } viewElementWrapper.appendChild(view); } diff --git a/scitos.ais/scitos.ais.core/src/main/resources/org/hmx/scitos/ais/stylesheet.xsl b/scitos.ais/scitos.ais.core/src/main/resources/org/hmx/scitos/ais/stylesheet.xsl index 1ece908..c5cca54 100644 --- a/scitos.ais/scitos.ais.core/src/main/resources/org/hmx/scitos/ais/stylesheet.xsl +++ b/scitos.ais/scitos.ais.core/src/main/resources/org/hmx/scitos/ais/stylesheet.xsl @@ -1,7 +1,7 @@ - + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ais="http://www.hermeneutix.org/schema/ais/1.0"> + Autobiographical Interview Scoring (presented by SciToS) @@ -113,7 +113,7 @@ span.detail-end { float: right; } .accordion section:not(:target) .section-content { display:none; } .accordion section:target .section-content { padding-top: 0; } .paragraph { padding: 0.25em 1em; } - + - + - + .token.detail- @@ -173,7 +173,7 @@ span.detail-end { float: right; } - +

@@ -184,28 +184,28 @@ span.detail-end { float: right; } Interview Token Count - + - + + test="1 < count(../ais:Interview[@participant=current()/@participant])"> - + - + @@ -216,7 +216,7 @@ span.detail-end { float: right; }

- +
@@ -229,7 +229,7 @@ span.detail-end { float: right; } - + @@ -240,29 +240,29 @@ span.detail-end { float: right; } - + - + + select="count($interview//ais:Detail[contains($childCodes,concat(' ',@code,' '))])" /> + select="count($interview//ais:Detail[@code=$category/@code])" /> - + - + @@ -279,7 +279,7 @@ span.detail-end { float: right; } + test="1 < count(../ais:Interview[@participant=current()/@participant])"> @@ -287,42 +287,42 @@ span.detail-end { float: right; }
- +
- +

- +

- +
- + + select="1 + count(//ais:Category[@code = current()/../@code]/preceding::ais:Category)" /> + select="local-name(preceding-sibling::*[1]) = 'Detail' or (count(preceding-sibling::ais:Token) = 0 and position() > 1)" /> - + select="local-name(following-sibling::*[1]) = 'Detail' or (count(following-sibling::ais:Token) = 0 and position() < last())" /> + + test="local-name(..) = 'Detail' and count(preceding-sibling::ais:Token) = 0"> - +