Page 1 of 1

Allowing external XML/RNG file to dictate optional content for web custom framework

Posted: Thu Sep 15, 2016 3:26 pm
by Aliahc
Hi,

I have a predicament on optional content that comes out of custom frameworks for Web Author only allowing use of a single schema, and that which must be embedded in the custom framework files.

Here is my scenario (that will be common across my custom frameworks):

I have successfully created simple custom frameworks, each based on an RNG schema and a single CSS. I had also been able to create multiple sub-frameworks by defining different document structures within a single RNG and multiple CSS, and the fact I can present multiple templates from the same RNG means the end-user doesn't need to be concerned with the fact I have modeled multiple document structures in a single schema which gets picked up by a 'choice' within the <start> section of the RNG grammar. Also, it should be noted that we use the SharePoint plugin so any instances of using templates are saved in SharePoint documents location within a chosen subsite, whereby file structure local to the saved document is the SP location.

All that is fine for general structure whereby the templates are to be non-specific to context of document, only the structure of type of document is defined. For example, I have two templates under the same custom framework using a single RNG which allows engineers in my team to capture system components information either by a) a document template that categorizes entities and relationships are optionally defined, or b) a document template that enables a hierarchy/tree of entities to be defined, thus critically capturing relationships.

However, as these templates are not to be specific to any system, so that they can be reused for any number of (conceptual or physical) systems my team architect and develop, contextual content such as categories and entity types specific to a system must be dynamically defined during each INSTANCE of using the templates, but more importantly are to be restricted content so that these elements can be form-controlled (e.g. selection of content from a combobox which I have managed to achieve), but the engineers must be able to open an XML file or at worst, an RNG file, local to the saved instance of the chosen template, and add new content options to be picked up by the form so that they do not have to be manually inserted repeatedly in the main document (thus avoiding inconsistencies from typos etc).

Locally on my desktop I was easily able to achieve this by placing a second RNG file defining only content choices that gets included in the main one for document structure, but a custom framework only allows one schema OR an overriding by a different schema if I were to define it in the XML document. Please also bear in mind that only I, the technical author, have access to the custom framework configurations - everyone else will use these from the client-side sharepoint/web author interface. So any second RNG defining content choices would be to be sitting in a sharepoint folder for engineers to access and edit.

I get the feeling that XML catalogs would solve my problem, whereby my template can be predefined as pointing to a local file (e.g. called contentChoices.rng) in the same SP folder as the instance document, but I don't know enough about XML catalogs to know whether the main RNG would still be used and allow inclusion of this content choice rng sitting in a different location (as the main schema is in the frameworks folder server-side) - or perhaps there is a way (and this would be preferred) whereby the main RNG would allow content choices to be picked up from a referenced XML file (e.g. created as contentChoices.xml) local to the instance of the main document template within the sharepoint folder. But I'm not sure if RelaxNG or web author/custom frameworks would allow for referencing files that have not been created yet at the point of just being a template.

I hope that wasn't too confusing. The problem I feel is actually quite simple and the fact it can be done locally frustrates me that I seem to be hitting barriers through custom frameworks and indeed the fact web author relies on the schema location to be in a different place to the user's local file system (sharepoint in my case) such that I can't predefine any local schema location in the main schema because this is unknown (e.g. new documents created in different sharepoint sites and subsites). I also feel my lack of knowledge in XML catalogs and indeed how to do XML referencing (I still can't get my head around namespaces) is hindering me.

I would really appreciate any solutions.

Many thanks,

Aliah

Re: Allowing external XML/RNG file to dictate optional content for web custom framework

Posted: Fri Sep 16, 2016 10:52 am
by cristi_talau
Hello,

As far as I understand you want element values to be controlled by an XML file. This file resides by default in the frameworks folder, but engineers should be able to override it by placing an XML values configuration file in the same folder (on Sharepoint) as the edited XML document.

I propose the following solution that relies on the CSS used for presenting the document instead of the Schema.

1. Associate the following LESS file with the documents in your framework:

Code: Select all


// By default, load the values.xml file from the framewotk directory.
:root elementWithChoices {
.controlled-values(oxy_url("${framework}", "values.xml"));
}
// If specified in the root element, another choices file is used.
:root[choices] elementWithChoices {
.controlled-values(oxy_xpath("/*/@choices", processChangeMarkers, false, evaluate, dynamic-once));
}

.controlled-values(@valuesFile) {
//The oxy_concat expression just composes an XPath expression like the one below:
//
// string-join(doc('values.xml')//my-element-name/*/text(), ',')
//
@xpath: oxy_concat("string-join(doc('", @valuesFile, "')//", oxy_name(), "/*/text(), ',')");
content: oxy_combobox(
edit, '#text',
editable, false,
values, oxy_xpath(@xpath, processChangeMarkers, false, static)
);
visibility: -oxy-collapse-text;
}
(for better readability I created a gist: https://gist.github.com/ctalau/3ccdfe8a ... 3c0ae1d5f0 )

2. The format of the

Code: Select all

values.xml
file is the following:

Code: Select all


<values>
<elementWithChoices>
<value>a1</value>
<value>a2</value>
<value>a3</value>
</elementWithChoices>
</values>
3. The file to be edited contains something like this:

Code: Select all


<root choices="values.xml">
...
<elementWithChoices/>
...
</root>
In this solution, the engineers have to specify the location of the values file as an attribute on the root of the XML document (you can create a toolbar action for that). If no value is specified, a default file from the framework directory is used.

You can tweak this solution in various ways. Please let me know if this sounds promising to you.

Regarding catalogs, you cannot use to implement something like this: import this schema and if it does not exist import another one.

Best,
Cristian

Re: Allowing external XML/RNG file to dictate optional content for web custom framework

Posted: Fri Sep 16, 2016 12:56 pm
by Aliahc
Hi there,

Thanks for that idea - and very close to what I was originally trying with the values of the combobox function, but couldn't work out the referencing of a different file. The ability to override default values is probably the key thing here so it allows a template to be non-specific while defining values in an external file.

I won't pursue XML catalog, so I'll try this out and return here with feedback.

Many thanks!

Re: Allowing external XML/RNG file to dictate optional content for web custom framework

Posted: Fri Sep 16, 2016 2:14 pm
by cristi_talau
Hello,

If you want to also receive validation errors for values that are not among the specified ones (perhaps introduced by editing in text-mode), you can use a Schematron schema besides the RNG one that you already have.

The following Schematron file should validate element values against the values read from the same XML file.

Code: Select all


<?xml version="1.0" encoding="UTF-8"?>
<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2"
xmlns:sqf="http://www.schematron-quickfix.com/validator/process">
<!-- General variables for the whole document. -->
<sch:let name="doc-uri" value="base-uri(.)"/>
<sch:let name="choices-file" value="/*/@choices"/>
<sch:let name="values-uri" value="resolve-uri($choices-file, $doc-uri)"/> <!-- Here we compute the location of the 'values.xml' file -->
<sch:let name="values-for-elements" value="doc($values-uri)"/>

<!-- Abstract pattern to be instantiated for each element with constrained values -->
<sch:pattern abstract="true" id="value-constraint">
<sch:title>Constrain element values</sch:title>
<sch:rule context="$element-name">
<sch:let name="crt-text" value="text()"/>
<sch:let name="choices" value="$values-for-elements//$element-name/*/text()"/>
<sch:let name="matches" value="$values-for-elements//$element-name/*[text() = $crt-text]/text()"/>
<sch:assert test="not(empty($matches))">
Invalid value for element <sch:value-of select="local-name(.)"/>: "<sch:value-of select="$crt-text"/>" is not among <sch:value-of select="string-join($choices, ',')"/>
</sch:assert>

</sch:rule>
</sch:pattern>

<!-- This is an instance of the rule for a particular element -->
<sch:pattern is-a="value-constraint">
<sch:param name="element-name" value="elementWithChoices"/>
</sch:pattern>
</sch:schema>
Best,
Cristian

Re: Allowing external XML/RNG file to dictate optional content for web custom framework

Posted: Tue Sep 20, 2016 1:42 pm
by Aliahc
I'm afraid this hasn't quite worked for me.

My original setup was (a stripped down version to give an example):

RelaxNG schema definition of the main elements - with choices 'hardcoded' into the schema which as you can understand isn't ideal.

Code: Select all


<define name="root">
<element name="system">
<element name="entity">
<attribute name="entity_type">
<choice>
<value>type1</value>
<value>type1</value>
</choice>
</attribute>
<element name="info">
<element name="entity_name"><text/></element>
<element name="entity_desc"><text/></element>
</element>
</element>
</element>
</define>
My CSS has the following definitions (only the relevant ones). Note that the only reason I made entity_type an attribute was because I was struggling get the oxy_combobox working and it only seemed to work when I used oxy_editor editing on an attribute of the parent element (entity).

Code: Select all


info {
display: table-row;
}

[entity_type] {
padding: 5px;
}

entity_name,
entity_desc {
display: table-cell;
}

entity:before {
content:
oxy_editor(
type, combo,
edit, '@entity_type',
editable, false
)
}
Adopting the proposed solution I changed the schema to be:

Code: Select all


<define name="root">
[b]<attribute name="choices"><text/></attribute>[/b]
<element name="system">
<element name="entity">
[b]<attribute name="entity_type"><text/></attribute>[/b]
<element name="info">
<element name="entity_name"><text/></element>
<element name="entity_desc"><text/></element>
</element>
</element>
</element>
</define>
I commended out the css oxy_editor definition, and created the LESS file with adaptions (mainly the default file name and that it is an attribute) to my scenario:

Code: Select all


// By default, load the defaultValues.xml file from the framewotk directory.
:root [b][entity_type][/b] {
.controlled-values(oxy_url("${framework}", "defaultValues.xml"));
}
// If specified in the root element, another choices file is used.
:root[choices] [b][entity_type] [/b]{
.controlled-values(oxy_xpath("/*/@choices", processChangeMarkers, false, evaluate, dynamic-once));
}

.controlled-values(@valuesFile) {
@xpath: oxy_concat("string-join(doc('", @valuesFile, "')//", oxy_name(), "/*/text(), ',')");
content: oxy_combobox(
edit, '#text",
editable, false,
values, oxy_xpath(@xpath, processChangeMarkers, false, static)
);
visibility: -oxy-collapse-text;
}
whereby the file defaultValues.xml looks like this:

Code: Select all


<values>
<entity_type>
<value>type1</value>
<value>type2</value>
</entity_type>
</values>
I get a combobox in the right place (i.e. picking up I want to style the entity_type attribute, but not pulling in any values.

I believe I'm very close to achieving it but I'm missing something fundamental either in the xpath definition or the oxy_combobox, but I really have no idea what else could be wrong. Only that I am styling an attribute? To be honest I changed it to an element and it was still giving me the same result - no list of values. I can only conclude that it should make no difference because the oxy_name is picking up on the name of the attribute or element, regardless and matching it to the values file.

Any ideas?

Re: Allowing external XML/RNG file to dictate optional content for web custom framework

Posted: Tue Sep 20, 2016 2:25 pm
by cristi_talau
Hello,

It is much simpler if "entity_type" is an element. You cannot style an attribute, you can only style an element which has that attribute and "oxy-name" returns the name of the element.

Here is the setup that worked for me. This is the edited XML file:

Code: Select all

<?xml-stylesheet type="text/css" href="catapult.less"?>
<root choices="values.xml">
<system>
<entity_type>type1</entity_type>
<entity_name>name</entity_name>
<entity_info>info</entity_info>
</system>
</root>
The following less file:

Code: Select all

entity_name,
entity_desc,
entity_info {
display: table-cell;
}

// By default, load the defaultValues.xml file from the framewotk directory.
:root entity_type {
.controlled-values(oxy_url("${framework}", "defaultValues.xml"));
}
// If specified in the root element, another choices file is used.
:root[choices] entity_type {
.controlled-values(oxy_xpath("/*/@choices", processChangeMarkers, false, evaluate, dynamic-once));
}

.controlled-values(@valuesFile) {
@xpath: oxy_concat("string-join(doc('", @valuesFile, "')//", oxy_name(), "/*/text(), ',')");
content: oxy_combobox(
edit, "#text",
editable, false,
values, oxy_xpath(@xpath, processChangeMarkers, false, static)
);
visibility: -oxy-collapse-text;
}
and this is the values.xml file:

Code: Select all


<values>
<entity_type>
<value>type1</value>
<value>type2</value>
</entity_type>
</values>
Can you try this on your side?

Best,
Cristian

Re: Allowing external XML/RNG file to dictate optional content for web custom framework

Posted: Tue Sep 20, 2016 5:29 pm
by Aliahc
Hi there - thanks for that - really helped. I am almost there it seems but still having some issues which are proving particularly problematic for web author.

Firstly, I have made the attribute into an an element, and IF I specify an alternate file, then it pulls through the values and it's perfect - on desktop author. Trying to test the framework on web author test server does not allow the file to be loaded. So I think there may be an issue of how Web Author responds to less files?

Before specifying an alternate file however, the choices attribute is empty, and the less file should pick up on the hardcoded filename in the frameworks directory - it doesn't. Instead I get these errors:

Parse Error : // By default, load the defaultValues.xml file from the framework directory.
:root entity_type {
.controlled-values(oxy_url("${framework}", "defaultValues.xml"));
}

System ID: C:\Users\....framework.css
Severity: error
Description: [CSS]:XPath failed: XPath failed due to: I/O error reported by XML parser processing file:/C:/Users/...Untitled15.xml: C:\Users\...Untitled15.xml (The system cannot find the file specified)

I tried removing comments in the less file.

This wouldn't be a huge problem if, for now, I forced a set filename value in choices so it always picked up on a local file of a specific name. But as I said, when I run the it on web author test server, I get a 'file could not be loaded' error. When I remove all references to the less file, it loads the document, so it is clearly something to do with that.

I think it is a problem I am having in associating the less file. I can't associate it directly in the doc type templates, as I don't want css or less files hanging around outside the framework directly, and it is expecting it to be in the local directory of the saved doc from template (i.e. href="choices.less").

So I tried two things - either just associating the less file in the framework, or adding @import url("choices.less") to the main framework css. Both give me the error above.

All this is great, but if I can't even make it work with a forced external XML file name (the way it is working on desktop right now) on web author, then it is no use to me.

If you think I should send something to support to see if there's an issue in web author, then I'm happy to send along a stripped down version of the framework I have.

Thanks

Aliah

Re: Allowing external XML/RNG file to dictate optional content for web custom framework

Posted: Tue Sep 20, 2016 6:36 pm
by cristi_talau
Hello,

The error says the values file cannot be found in your framework. The quick-est workaround is to create such a file (with no choices for example).

The problem seems to be in the way oXygen executes XPath expressions. I expected that the XPath expression is not evaluated if the CSS rule does not match. I will investigate this problem and let you know if you can do something about it.

Best,
Cristian

Re: Allowing external XML/RNG file to dictate optional content for web custom framework

Posted: Tue Sep 20, 2016 7:00 pm
by Aliahc
Hi there,

Actually I have always had dafaultValues.xml file in the framework, that is why it is confusing. I will send a copy of my framework to the support email - it might let you identify the issue.

It is worth mentioning that when I use @import of choices.css in the main css, in web author it gives me a detailed issue of why the document could not be loaded:

Details:

TypeError: Cannot find function bind in object
function _math(fn, unit, n) {
if (!(n instanceof tree.Dimension)) {
throw {type:"Argument", message:"argument must be a number"};
}
if (unit == null) {
unit = n.unit;
} else {
n = n.unify();
}
return new (tree.Dimension)(fn(parseFloat(n.value)), unit);
}
.

Although, I have no idea if that means just the same thing that it can't find the file!

Thanks for your help.

Aliah