Skip to content

Commit

Permalink
added tag value validation
Browse files Browse the repository at this point in the history
  • Loading branch information
Dragos0000 committed Jan 23, 2025
1 parent f6c70f1 commit 9215971
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/common/checkers.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@
<xsl:param name="tagName"/>
<xsl:sequence
select="
if (fn:matches($tagName, '^(:\w+|[a-z][-a-z0-9]*:[-a-zA-Z0-9_@]+)$')) then
if (fn:matches($tagName, '^[a-z][-a-z0-9]*:[-a-zA-Z0-9_]+(?:@[a-zA-Z]+|\\^\\^[-a-zA-Z0-9_]+|&lt;&gt;)?$')) then
fn:true()
else
fn:false()"
Expand Down
107 changes: 107 additions & 0 deletions src/common/utils.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -632,5 +632,112 @@
<xsl:namespace name="{./@name}" select="./@value"/>
</xsl:for-each>
</xsl:template>


<!-- Grouped Datatypes as Lists -->
<xsl:variable name="numericDatatypes" as="xs:string*">
<xsl:sequence select="'xsd:integer', 'xsd:decimal', 'xsd:double', 'xsd:float',
'xsd:byte', 'xsd:short', 'xsd:int', 'xsd:long',
'xsd:negativeInteger', 'xsd:nonNegativeInteger',
'xsd:positiveInteger', 'xsd:nonPositiveInteger',
'xsd:unsignedByte', 'xsd:unsignedShort',
'xsd:unsignedInt', 'xsd:unsignedLong'"/>
</xsl:variable>

<xsl:variable name="booleanDatatypes" as="xs:string*">
<xsl:sequence select="'xsd:boolean'"/>
</xsl:variable>

<xsl:variable name="dateTimeDatatypes" as="xs:string*">
<xsl:sequence select="'xsd:date', 'xsd:time', 'xsd:dateTime', 'xsd:dateTimeStamp'"/>
</xsl:variable>

<xsl:variable name="stringDatatypes" as="xs:string*">
<xsl:sequence select="'xsd:string', 'xsd:normalizedString', 'xsd:token',
'xsd:Name', 'xsd:NCName', 'xsd:NMTOKEN',
'xsd:language', 'rdf:PlainLiteral', 'rdf:langString'"/>
</xsl:variable>


<xd:doc>
<xd:desc>
This function validates the value entered by the user in a tag against its corresponding datatype.

Due to XSLT limitations, specifically with the castable as expression, the validation process can't be done dynamically
so multiple datatypes needs to be grouped in the validation process. For instance:

Data types such as xsd:integer and xsd:double are grouped under xs:double for validation purposes.
Similarly, other related data types are grouped into predefined variables.

If a new custom data type is introduced, it must be added to the appropriate grouping variable to ensure validation.
This is a workaround due limitations of XSLT
</xd:desc>
<xd:param name="tagValue"/>
<xd:param name="datatypeQName"/>
</xd:doc>
<xsl:function name="f:validateTagValue" as="xs:boolean">
<xsl:param name="tagValue" as="xs:string"/>
<xsl:param name="datatypeQName" as="xs:string"/>

<!-- Validation based on resolved datatype -->
<xsl:choose>
<!-- Numeric Types -->
<xsl:when test="$datatypeQName = $numericDatatypes">
<xsl:if test="not($tagValue castable as xs:double)">
<xsl:sequence select="fn:error(
xs:QName('invalidValueError'),
concat('Error: Value ', $tagValue, ' is not valid for numeric type ', $datatypeQName, '.')
)"/>
</xsl:if>
</xsl:when>

<!-- Boolean Type -->
<xsl:when test="$datatypeQName = $booleanDatatypes">
<xsl:if test="not($tagValue castable as xs:boolean)">
<xsl:sequence select="fn:error(
xs:QName('invalidValueError'),
concat('Error: Value ', $tagValue, ' is not valid for boolean type ', $datatypeQName, '.')
)"/>
</xsl:if>
</xsl:when>

<!-- Date and Time Types -->
<xsl:when test="$datatypeQName = $dateTimeDatatypes">
<xsl:if test="not($tagValue castable as xs:dateTime)">
<xsl:sequence select="fn:error(
xs:QName('invalidValueError'),
concat('Error: Value ', $tagValue, ' is not valid for date/time type ', $datatypeQName, '.')
)"/>
</xsl:if>
</xsl:when>

<!-- Strings and Text Types -->
<xsl:when test="$datatypeQName = $stringDatatypes">
<!-- Strings are always valid -->
</xsl:when>

<!-- URI Validation -->
<xsl:when test="$datatypeQName = 'xsd:anyURI'">
<xsl:if test="not($tagValue castable as xs:anyURI)">
<xsl:sequence select="fn:error(
xs:QName('invalidValueError'),
concat('Error: Value ', $tagValue, ' is not a valid URI.')
)"/>
</xsl:if>
</xsl:when>

<!-- Unsupported Types -->
<xsl:otherwise>
<xsl:sequence select="fn:error(
xs:QName('invalidValueError'),
concat('Error: Unsupported datatype ', $datatypeQName, '.')
)"/>
</xsl:otherwise>
</xsl:choose>

<!-- Return true for valid values -->
<xsl:sequence select="fn:true()"/>
</xsl:function>


</xsl:stylesheet>
17 changes: 12 additions & 5 deletions src/owl-core-lib/descriptors-owl-core.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -112,34 +112,39 @@
</xsl:element>
</xsl:when>
<xsl:when test="fn:contains($tagName, '^^')">
<xsl:variable name="datatype" select="fn:substring-after($tagName, '^^')"/>
<xsl:variable name="datatypePrefix" select="fn:substring-before($datatype, ':')"/>
<xsl:variable name="datatypeValue" select="fn:substring-after($datatype, ':')"/>
<xsl:variable name="datatypeCompactURI" select="fn:substring-after($tagName, '^^')"/>
<xsl:variable name="datatypePrefix" select="fn:substring-before($datatypeCompactURI, ':')"/>
<xsl:variable name="datatypeLocalName" select="fn:substring-after($datatypeCompactURI, ':')"/>
<xsl:variable name="expandedDatatypePrefix" select="f:getNamespaceURI($datatypePrefix)"/>
<xsl:if test="f:validateTagValue($tagValue,$datatypeCompactURI)">


<xsl:choose>
<xsl:when test="$datatypeValue='string'">
<xsl:when test="$datatypeLocalName='string'">
<xsl:element name="{fn:substring-before($tagName,'^^')}" namespace="{f:getNamespaceURI(fn:substring-before($tagName, ':'))}">
<xsl:value-of select="$tagValue"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{fn:substring-before($tagName,'^^')}" namespace="{f:getNamespaceURI(fn:substring-before($tagName, ':'))}">
<xsl:attribute name="rdf:datatype">
<xsl:value-of select="fn:concat($expandedDatatypePrefix,$datatypeValue)"/>
<xsl:value-of select="fn:concat($expandedDatatypePrefix,$datatypeLocalName)"/>
</xsl:attribute>
<xsl:value-of select="$tagValue"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:when>
<xsl:when test="fn:contains($tagName, '&lt;&gt;')">
<xsl:if test="f:validateTagValue($tagValue,'xsd:anyURI')">
<xsl:variable name="tagPrefix" select="fn:substring-before($tagName, ':')"/>
<xsl:element name="{fn:substring-before($tagName,'&lt;&gt;')}" namespace="{f:getNamespaceURI(fn:substring-before($tagName, ':'))}">
<xsl:attribute name="rdf:resource">
<xsl:value-of select="$tagValue"/>
</xsl:attribute>
</xsl:element>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{$tagName}" namespace="{f:getNamespaceURI(fn:substring-before($tagName, ':'))}">
Expand All @@ -153,5 +158,7 @@
</rdf:Description>
</xsl:template>




</xsl:stylesheet>
41 changes: 41 additions & 0 deletions test/unitTests/test-common/test-utils.xspec
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,47 @@
</x:call>
<x:expect label="result" select="fn:true()"/>
</x:scenario>

<x:scenario label="Scenario for testing function f:validateTagValue ">
<x:scenario label="valid boolean">
<x:call function="f:validateTagValue">
<x:param name="tagValue" select="'true'"/>
<x:param name="datatypeQName" select="'xsd:boolean'"/>
</x:call>
<x:expect label="result" select="fn:true()"/>
</x:scenario>

<x:scenario label="valid integer">
<x:call function="f:validateTagValue">
<x:param name="tagValue" select="'2'"/>
<x:param name="datatypeQName" select="'xsd:int'"/>
</x:call>
<x:expect label="result" select="fn:true()"/>
</x:scenario>

<x:scenario label="valid URI">
<x:call function="f:validateTagValue">
<x:param name="tagValue" select="'http://www.w3.org/2001/XMLSchema#string'"/>
<x:param name="datatypeQName" select="'xsd:anyURI'"/>
</x:call>
<x:expect label="result" select="fn:true()"/>
</x:scenario>

<x:scenario label="invalid URI" catch="yes">
<x:call function="f:validateTagValue">
<x:param name="tagValue" select="'invalid_uri'"/>
<x:param name="datatypeQName" select="'xsd:anyURI'"/>
</x:call>
</x:scenario>

<x:scenario label="invalid integer" catch="yes">
<x:call function="f:validateTagValue">
<x:param name="tagValue" select="'integer'"/>
<x:param name="datatypeQName" select="'xsd:int'"/>
</x:call>
</x:scenario>

</x:scenario>


<x:scenario label="Scenario for testing function buildPropertyShapeURI">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@
<x:call template="invalidTagName">
<x:param name="element" href="../../testData/ePO_core_with_tags.xml" select="/xmi:XMI/xmi:Extension[1]/elements[1]/element[211]"/>
</x:call>
<x:expect label="expect a Description Element" test="count(/dd)=3"/>
<x:expect label="expect a Description Element" test="count(/dd)=4"/>
</x:scenario>

<x:scenario label="Scenario for finding a tag without name in a class ">
Expand Down

0 comments on commit 9215971

Please sign in to comment.