Главная » XSLT » Генерация тематических карт из UML-модели с помощью XMI

0

Задача

Вы хотели бы воспользоваться своим любимым инструментом UML-моде- лирования с поддержкой XMI для создания описаний тематических карт на языке XTM.

Решение

Читателям, не знакомым с тематическими картами, возможно, стоит сначала прочитать раздел «Обсуждение».

Поскольку UML не задумывался для представления тематических карт, этот пример будет работать только при соблюдении определенных соглашений. По большей части, они касаются использования конкретных стереотипов UML. Стерео­тип – это механизм расширения UML, который позволяет ассоциировать с любым классификатором UML некий символ, который означает, что этому классификатору приписана определенная пользователем семантика. Для реализации тематических карт на UML нам потребуются стереотипы, перечисленные в таблице 13.2.

Таблица 13.2. Соглашения об описании тематических карт на языке UML

Помимо этих стереотипов, используются следующие отображения UML на Topic Map:

?               Класс UML

Моделирует тему Topic Map, если только не задан стереотип, отличный от topic. В качестве базового имени темы используется имя класса. Если у класса есть атрибут ID. то в качестве идентификатора темы используется его значение по умолчанию. Если атрибута ID нет, то в качестве идентифи­катора темы выступает само имя класса.

?               Ассоциация UML

Моделирует ассоциацию Topic Map, если только не задан стереотип, обознача­ющий иное. Имя ассоциации UML отображается на имя ассоциации Topic Map. Спецификатор роли UML становится спецификатором роли Topic Map.

?               UML создает экземпляр ассоциации Моделирует отношение instanceOf в Topic Map.

?               Простая ассоциация типа «обобщение» (наследование) в UML Используется в качестве сокращенного способа задания канонической ас­социации superclass-subclass, в которой оконечным элементам автомати­чески назначаются роли superclass и subclass. То же самое отношение свя­зывает классы со стереотипом baseName с классами-темами, для которых они представляют имя в альтернативном контексте. Обобщение со стерео­типом variant определяет также варианты тем.

Если ваша версия Rational Rose не сохраняет модели в формате XMI, заг- ® рузите надстройку XMI или RoseXMI со страницы http://www.rational.com/ support/downloadcenter/addins/rose/index.jsp. Я тестировал этот пример только в Rose, но другие инструменты для работы с UML, например Together Control Center компании TogetherSoft, тоже поддерживают XMI, и для них пример, скорее всего, будет работать.

Ниже приведена таблица стилей для преобразования XMI в XTM. Я опреде­лил несколько XML-компонентов для удобства работы с длинными именами:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE xslt [

<!– = = = = = = = = = = = = = = = = = = = = =– >

<!– Конструкции для организации верхнего уровня XMI –>

<!– = = = = = = = = = = = = = = = = = = = = =– >

<!ENTITY  FC  "Foundation.Core">

<!ENTITY  FX  "Foundation.Extension_Mechanisms">

<!ENTITY  FD  "Foundation.Data_Types">

<!ENTITY      MM "Model_Management.Model">

<!ENTITY ME "&FC;.ModelElement">

<!– = = = = = = = = = = = = = = = = = = = = =– >

<!– Сокращения для основных элементов XMI, –> <!– представляющих наибольший интерес для –>

<!– этой таблицы стилей.                    –>

<!– = = = = = = = = = = = = = = = = = = = = =– >

<!– Элемент UML общего вида –> <!ENTITY ELEM "&FC;.Namespace.ownedElement"> <!– Ассоциация как единое целое –> <!ENTITY ASSOC "&FC;.Association">

<!– Часть, представляющая соединение ассоциации –>

<!ENTITY CONN "&ASSOC;.connection">

<!– Концы ассоциации. –>

<!ENTITY END "&ASSOC;End">

<!ENTITY CONNEND "&CONN;/&END;">

<!ENTITY ENDTYPE "&END;.type">

<!– Класс UML –>

<!ENTITY CLASS "&FC;.Class">

<!– Имя сущности UML –>

<!ENTITY NAME "&FC;.ModelElement.name"> <!– Стереотип UML — >

<!ENTITY STEREOTYPE "&ME;.stereotype/&FX;.Stereotype"> <!– Место, где сохраняется документация UML в формате XMI. –> <!– Используется для данных о ресурсах –> <!ENTITY TAGGEDVALUE

"&ME;.taggedValue/&FX;.TaggedValue/&FX;.TaggedValue.value"> <!– Отношение Supertype (наследование) –> <!ENTITY SUPERTYPE "&FC;.Generalization.supertype"> <!ENTITY SUBTYPE "&FC;.Generalization.subtype"> <!ENTITY SUPPLIER "&FC;.Dependency.supplier"> <!ENTITY CLIENT "&FC;.Dependency.client"> <!ENTITY DEPENDENCY

"/XMI/XMI.content/&MM;/&ELEM;/&FC;.Dependency"> <!ENTITY EXPRBODY

"&FC;.Attribute.initialValue/&FD;.Expression/&FD;.Expression.body"> <!ENTITY ATTR "&CLASS;ifier.feature/&FC;.Attribute"> <!– Используется для указания на стандартную спецификацию XTM –> <!ENTITY TM.ORG "http://www.topicmaps.org/xtm/index.html">

]>

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

xmlns:xtm="http://www.topicmaps.org/xtm/1.0"

xmlns:xlink="http://www.w3.org/1999/xlink">

<xsl:param name="termOnErr" select="true( )"/>

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

Воспользуемся ключами, чтобы упростить идентификацию стереотипов и обойти ассоциации UML, в которых встречаются перекрестные ссылки между атрибутами xmi.id и xmi.idref:

<!– Индексировать классы по имени –>

<xsl:key name="classKey" match="&CLASS;" use="@xmi.id"/> <!– Индексировать стереотипы по имени и xmi.id –> <xsl:key name="stereotypeKey"

match="&FX;.Stereotype" use="@xmi.id"/> <xsl:key name="stereotypeKey"

match="&FX;.Stereotype" use="&NAME;"/>

<!— Для кодирования тематических карт в UML применяются атрибуты xmi:id –> <!— стереотипов. Мы воспользуемся ими в качестве эффективного средства —> <!– проверки того, присоединен ли стереотип к элементу –>

<xsl:variable name="OCCURENCE_ID"

select="key(‘stereotypeKey’,,occurence,)/@xmi.id"/> <xsl:variable name="RESOURCE_ID"

select="key(‘stereotypeKey’,,resource,)/@xmi.id"/> <xsl:variable name="TOPIC_ID"

select="key(‘stereotypeKey’,,topic,)/@xmi.id"/> <xsl:variable name="SUBJECT_ID"

select="key(‘stereotypeKey’,,subject,)/@xmi.id"/> <xsl:variable name="BASENAME_ID"

select="key(‘stereotypeKey’,,baseName,)/@xmi.id"/> <xsl:variable name="SCOPE_ID"

select="key(‘stereotypeKey’,,scope,)/@xmi.id"/>

<xsl:variable name="VARIANT_ID"

select="key(‘stereotypeKey’,,variant,)/@xmi.id"/>

Преобразовать UML-модель, записанную на языке XMI, в тематическую кар­ту можно в два прохода. Сначала импортируем темы из классов, а затем – ассоци­ации XTM из ассоциаций UML:

<xsl:template match="/"> <xtm:topicMap>

<xsl:apply-templates mode="topics"/> <xsl:apply-templates mode="associations"/> </xtm:topicMap> </xsl:template>

В темы следует транслировать только классы без стереотипа или со стереоти­пом topic. Все остальные встречающиеся в модели классы – это представления,

на которые может ссылаться тема, например, индикаторы предмета и ресурсы:

<!– = = = = = = = = = = = = = = = = = = = = =– >

<!– Трансляция классов UML в темы –>

<!– = = = = = = = = = = = = = = = = = = = = =– >

<xsl:template match="&ELEM;/&CLASS;" mode="topics"> <!– Темы моделируются классами без стереотипа –> <!– или со стереотипом ‘topic’     –>

<xsl:if test="not(&STEREOTYPE;/@xmi.idref) or

&STEREOTYPE;/@xmi.idref = $TOPIC_ID"> <xsl:variable name="topicId">

<xsl:call-template name="getTopicId">

<xsl:with-param name="class" select="."/> <xsl:with-param name="prefix" select="”"/> </xsl:call-template> </xsl:variable> <xtm:topic id="{$topicId}">

<!– Этот цикл for-each нужен только для переключения контекста –> <!– на необязательный атрибут Core.Attribute с именем ‘subjectIdentityid’ –>

<xsl:for-each select="&ATTR;[&NAME; = ‘subjectIdentity’]"> <xtm:subjectIdentity>

<xtm:subjectIdicatorRef xlink:href="{&EXPRBODY;}"/> </xtm:subjectIdentity> </xsl:for-each> <xtm:baseName>

<xtm:baseNameString>

<xsl:value-of select="&NAME;"/> </xtm:baseNameString>

</xtm:baseName>

<xsl:apply-templates select="." mode="getAlternateBaseNames"/> <xsl:apply-templates select="." mode="getVariants"/> <xsl:apply-templates select="." mode="getInstanceOf">

<xsl:with-param name="classId" select="@xmi.id"/> </xsl:apply-templates>

<xsl:apply-templates select="." mode="getOccurences"/> </xtm:topic> </xsl:if> </xsl:template>

<!– Вернуть идентификатор темы из класса темы; это –> <!– либо значение атрибута id, либо само имя класса —> <xsl:template name="getTopicId"> <xsl:param name="class"/> <xsl:param name="prefix" select="’#’"/> <xsl:for-each select="$class"> <xsl:choose>

<xsl:when test="&ATTR;/&NAME; = ‘id’ ">

<xsl:value-of select="&ATTR;[&NAME; = ‘id’]/&EXPRBODY;"/> </xsl:when> <xsl:otherwise>

<xsl:value-of select="concat($prefix,&NAME;)"/> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template>

<!– Вернуть идентификатор предмета из класса предмета; это –> <!– либо значение атрибута subjectIdentity, либо само имя класса –> <xsl:template name="getSubjectIdentity"> <xsl:param name="class"/> <xsl:for-each select="$class"> <xsl:choose>

<xsl:when test="&ATTR;/&NAME; = ‘subjectIdentity’ "> <xsl:value-of select="&ATTR;[&NAME; =

‘subjectIdentity’]&EXPRBODY;"/>

</xsl:when> <xsl:otherwise>

<xsl:value-of select="concat(‘#’,&NAME;)"/> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template>

<!– Веpнyть идентификaтop pесypсa из класса pесypсa; это –> <!– либо значение aтpибyтa resourceName, либо само имя класса –> <xsl:template name="getResourceIdentity"> <xsl:param name="class"/> <xsl:for-each select="$class"> <xsl:choose>

<xsl:when test="&ATTR;/&NAME; = ‘resourceName’ "> <xsl:value-of select="&ATTR;[&NAME; =

‘resourceName’]/&EXPRBODY;"/>

</xsl:when> <xsl:otherwise>

<xsl:value-of select="concat(‘#’,&NAME;)"/> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template>

Альтернативные базовые имена и варианты можно моделировать как специа­лизации базового класса темы, пользуясь ассоциациями обобщения в UML. В за­висимости от точки зрения это может показаться естественным делом или грубым осквернением идеи. Так или иначе, этот прием эффективен и на UML-диаграммах обозначается визуально, так что можно не полагаться на одни лишь метки стерео­типов:

<!– Aльтеpнaтивные базовые имена находятся путем обхода –> <!— отношений обобщения и поиска стеpеoтипoв baseName —>

<xsl:template match="&ELEM;/&CLASS;" mode="getAlternateBaseNames"> <xsl:variable name="xmiId" select="@xmi.id"/> <xsl:for-each select="../&FC;.Generalization

[&SUPERTYPE;/&CLASS;/@xmi.idref = $xmiId]"> <xsl:variable name="subtypeXmiId"

select="&FC;.Generalization.subtype/&CLASS;/@xmi.idref"/> <xsl:variable name="class" select="key(‘classKey’,$subtypeXmiId)"/> <xsl:if test="$class/&STEREOTYPE;/@xmi.idref = $BASENAME_ID"> <xsl:variable name="name" select="$class/&NAME;"/> <xtm:baseName>

<xsl:call-template name="getScope">

<xsl:with-param name="class" select="$class"/> </xsl:call-template> <xtm:baseNameString>

<xsl:value-of select="substring-after($name,'::’)"/> </xtm:baseNameString> </xtm:baseName> </xsl:if>

</xsl:for-each> </xsl:template>

<!— Варианты находятся путем обхода отношений обобщения —> <!– и поиска стереотипов baseName –>

<xsl:template match="&ELEM;/&CLASS;" mode="getVariants"> <xsl:variable name="xmiId" select="@xmi.id"/> <xsl:for-each select="../&FC;.Generalization

[&SUPERTYPE;/&CLASS;/@xmi.idref = $xmiId]"> <xsl:variable name="subtypeXmiId"

select="&FC;.Generalization.subtype/&CLASS;/@xmi.idref"/> <xsl:variable name="variantClass"

select="key(‘classKey’,$subtypeXmiId)"/> <xsl:if test="$variantClass/&STEREOTYPE;/@xmi.idref = $VARIANT_ID"> <xsl:variable name="name" select="$variantClass/&NAME;"/> <xtm:variant>

<xtm:variantName>

<xsl:call-template name="resourceRep">

<xsl:with-param name="class" select="$variantClass"/> </xsl:call-template> </xtm:variantName> <xtm:parameters>

<xsl:call-template name="getVariantParams">

<xsl:with-param name="class" select="$variantClass"/> </xsl:call-template> </xtm:parameters>

<!– Сменить контекст на этот вариант, чтобы найти вложенные —> <!– в него, если таковые существуют. –>

<xsl:apply-templates select="$variantClass" mode="getVariants"/> </xtm:variant> </xsl:if> </xsl:for-each> </xsl:template>

<!– Получить параметры варианта из атрибутов класса варианта –> <xsl:template name="getVariantParams"> <xsl:param name="class"/> <xsl:if test="not($class/&ATTR;)"> <xsl:message terminate="{$termOnErr}"> У варианта должен быть хотя бы один параметр. </xsl:message> </xsl:if>

<xsl:for-each select="$class/&ATTR;">

<!– Параметр моделируется как индикатор предмета –>

<!– или как ссылка на тему –>

<xsl:choose>

<xsl:when test="&STEREOTYPE;/@xmi.idref = $SUBJECT_ID">

<xtm:subjectIdicatorRef xlink:href="{&EXPRBODY;}"/> </xsl:when> <xsl:otherwise>

<xtm:topicRef xlink:href="{&EXPRBODY;}"/> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template>

Вхождения в смысле Topic Map моделируются как ассоциации с классами, со­держащими ссылки на ресурсы или данные. Поскольку встроенные данные ре­сурса могут оказаться слишком длинными для значения атрибута, то в этом при­мере мы разрешаем использовать описание атрибута как альтернативный контейнер для данных ресурса:

<!– Вхождения в смысле Topic Map моделируются как ассоциации –> <!– с классами, содержащими ссылки на ресурсы или данные –> <xsl:template match="&ELEM;/&CLASS;" mode="getOccurences"> <xsl:variable name="xmiId" select="@xmi.id"/>

<!– Просмотреть все ассоциации, в которых участвует данный класс –> <xsl:for-each

select="../&ASSOC;

[&CONN;/*/&ENDTYPE;/&CLASS;/@xmi.idref = $xmiId]"> <!– Проверить наличие стереотипа occurrence –> <xsl:if test="&STEREOTYPE;/@xmi.idref = $OCCURENCE_ID">

<!– Получить идентификатор ресурса, взглянув на другой конец —> <!– ассоциации occurrence — > <xsl:variable name="resourceId"

select="&CONN;/*/&ENDTYPE;/&CLASS;

[gxmi.idref != $xmiId]/@xmi.idref"/> <!– Получить класс, представляющий ресурс –> <xsl:variable name="resourceClass"

select="key(‘classKey’,$resourceId)"/> <xtm:occurence>

<xsl:apply-templates select="." mode="getInstanceOf">

<xsl:with-param name="classId" select="$resourceId"/> </xsl:apply-templates>

<!–TODO: Пока еще не умею это моделировать! <xsl:call-template name="getScope">

<xsl:with-param name="class"/> </xsl:call-template>

– >

<!– Имеем либо ссылку на ресурс, либо данные ресурса. –> <!– Если у класса есть атрибут resourceData, то второе –> <xsl:call-template name="resourceRep">

<xsl:with-param name="class" select="$resourceClass"/> </xsl:call-template> </xtm:occurence> </xsl:if> </xsl:for-each> </xsl:template>

<!– Этот шаблон определяет, в каком виде представлен ресурс –> <xsl:template name="resourceRep"> <xsl:param name="class" /> <xsl:variable name="resourceData">

<!– for-each для смены контекста –>

<xsl:for-each select="$class/&ATTR;[&NAME; = ‘resourceData’]" <xsl:choose>

<!– Данные ресурса закодированы в документации –> <!– к атрибуту UML — > <xsl:when test="&TAGGEDVALUE;">

<xsl:value-of select="&TAGGEDVALUE;"/> </xsl:when>

<!– Данные ресурса закодированы в значении атрибута UML – <xsl:otherwise>

<xsl:value-of select="&EXPRBODY;"/> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:variable>

<!– Если данные ресурса найдены, используем их. –> <!– Иначе предполагаем, что пользователь имел в виду ссылку — <xsl:choose> <xsl:when test="string($resourceData)"> <xtm:resourceData>

<xsl:value-of select="$resourceData"/> </xtm:resourceData> </xsl:when> <xsl:otherwise>

<xsl:variable name="resource">

<xsl:call-template name="getResourceIdentity">

<xsl:with-param name="class" select="$class"/> </xsl:call-template> </xsl:variable>

<xtm:resourceRef xlink:href="{$resource}"/> </xsl:otherwise> </xsl:choose> </xsl:template>

Отношения XTM instanceOf моделируются как ассоциации зависимости в UML, которые также носят название instantiates (инстанцирует). Такое пред­ставление instanceOf выглядит вполне естественно:

<!– Этот шаблон проверяет, есть ли для класса темы –> <!– какие-нибудь ассоциации instanceOf –>

<xsl:template match="&ELEM;/&CLASS;" mode="getInstanceOf"> <xsl:param name="classId"/>

<!— В цикле обходим все отношения зависимости и —> <!– смотрим, как представлен экземпляр –> <xsl:for-each

select="&DEPENDENCY;[&CLIENT;/&CLASS;/@xmi.idref = $classId]"> <xtm:instanceOf>

<xsl:variable name="instanceClass"

select="key(‘classKey’,&SUPPLIER;/&CLASS;/@xmi.idref)"/> <!— Выясняем, как моделируется экземпляр: как предмет или как тема — >

<xsl:variable name="sterotypeId"

select="$instanceClass/&STEREOTYPE;/@xmi.idref"/>

<xsl:choose>

<!– Это случай индикатора предмета –> <xsl:when test="$sterotypeId = $SUBJECT_ID"> <xsl:variable name="subjectIdentity">

<xsl:call-template name="getSubjectIdentity">

<xsl:with-param name="class" select="$instanceClass"/> </xsl:call-template> </xsl:variable>

<xsl:if test="not(normalize-space($subjectIdentity))"> <xsl:message terminate="{$termOnErr}"> Предмет без идентификатора! </xsl:message> </xsl:if>

<xtm:subjectIdicatorRef xlink:href="{$subjectIdentity}"/> </xsl:when>

<!– В противном случае экземпляр представлен темой –> <xsl:when test="not($sterotypeId) or $sterotypeId = $TOPIC_ID"> <xsl:variable name="topicId">

<xsl:call-template name="getTopicId">

<xsl:with-param name="class" select="$instanceClass"/> </xsl:call-template>

</xsl:variable>

<xsl:if test="not(normalize-space($topicId))"> <xsl:message terminate="{$termOnErr}"> Тема без идентификатора! </xsl:message> </xsl:if>

<topicRef xlink:href="{$topicId}"/> </xsl:when> <xsl:otherwise>

<xsl:message terminate="{$termOnErr}">

<xsl:text>instanceOf должна указывать на тему или предмет. </xsl:text>

<xsl:value-of select="$instanceClass/&NAME;"/>

<xsl:text> is a </xsl:text>

<xsl:value-of

select="key(‘stereotypeKey’,$sterotypeId)/&NAME;"/> <xsl:text>.&#xa;</xsl:text> </xsl:message> </xsl:otherwise> </xsl:choose> </xtm:instanceOf> </xsl:for-each> </xsl:template>

<xsl:template name="getScope"> <xsl:param name="class"/>

<xsl:variable name="classesAssociations"

select="/*/XMI.content/*/&ELEM; /&ASSOC; [&CONN;/*/

&FC;.AssociationEnd.type/ &CLASS;/@xmi.idref = $class/@xmi.id]"/> <xsl:variable name="scopeAssociations"

select="$classesAssociations[

&FC;.ModelElement.stereotype/ &FX;.Stereotype/ @xmi.idref = $SCOPE_ID]"/> <xsl:if test="$scopeAssociations"> <xtm:scope>

<xsl:for-each select="$scopeAssociations"> <xsl:variable name="targetClassId"

select="&CONN;/*/&ENDTYPE;/&CLASS;

[gxmi.idref != $class/@xmi.id]/@xmi.idref"/> <xsl:variable name="targetClass"

select="key(‘classKey’,$targetClassId)"/> <xsl:call-template name="getScopeRef">

<xsl:with-param name="class" select="$targetClass"/> </xsl:call-template> </xsl:for-each> </xtm:scope> </xsl:if> </xsl:template>

<xsl:template name="getScopeRef"> <xsl:param name="class"/> <xsl:variable name="stereotypeId"

select="$class/&FC;.ModelElement.stereotype/ FX;.Stereotype/ @xmi.idref"/>

<xsl:choose>

<xsl:when test="not($stereotypeId) or $stereotypeId = $TOPIC_ID"> <xsl:variable name="topidId">

<xsl:call-template name="getTopicId">

<xsl:with-param name="class" select="$class"/> </xsl:call-template> </xsl:variable>

<xtm:topicRef xlink:href="{$topidId}"/> </xsl:when>

<xsl:when test="$stereotypeId = $SUBJECT_ID"> <xsl:variable name="subjectId">

<xsl:call-template name="getSubjectIdentity">

<xsl:with-param name="class" select="$class"/> </xsl:call-template> </xsl:variable>

<xtm:subjectIndicatorRef xlink:href="{$subjectId}"/> </xsl:when>

<xsl:when test="$stereotypeId = $RESOURCE_ID"> <xsl:variable name="resourceId">

<xsl:call-template name="getResourceIdentity">

<xsl:with-param name="class" select="$class"/> </xsl:call-template> </xsl:variable>

<xtm:resourceRef xlink:href="{$resourceId}"/> </xsl:when> <xsl:otherwise>

<xsl:message terminate="{$termOnErr}">

Контекстом может быть topicRef, subjectRef или resourceRef! </xsl:message>

</xsl:otherwise> </xsl:choose> </xsl:template>

<xsl:template match="text( )" mode="topics"/>

Следующие далее шаблоны – часть второго прохода, на котором ассоциации UML, которые еще не были обработаны в силу наличия специальных стереоти­пов, преобразуются в ассоциации Topic Map. Здесь стереотипом ассоциации явля­ется элемент topicRef, который определяет вид моделируемой ассоциации. Это, конечно, профанация самой идеи стереотипа, но что делать, если UML не предос­тавляет никакого другого подходящего места для хранения этой информации. Ассоциации в контексте – это проблема, которую я решил игнорировать. Со всех остальных точек зрения ассоциации UML хорошо ложатся на концепцию темати­ческих карт:

<!– = = = = = = = = = = = = = = = =– >

<!– АССОЦИАЦИИ UML В АССОЦИАЦИИ TOPIC MAP —>

<!– = = = = = = = = = = = = = = = =– >

<xsl:template match="&ASSOC;" mode="associations">

<!– Только именованные ассоциации UML могут быть ассоциациями Topic Map– >

<xsl:if test="normalize-space(&NAME;)"> <xtm:association id="{&NAME;}"> <xtm:instanceOf> <topicRef

xlink:href="{key(‘stereotypeKey’,

&STEREOTYPE;/@xmi.idref)/&NAME;}"/>

</xtm:instanceOf>

<xsl:for-each select="&CONNEND;"> <xtm:member>

<xtm:roleSpec>

<xtm:topicRef xlink:href="{&NAME;}"/> </xtm:roleSpec> <xsl:variable name="topicId">

<xsl:call-template name="getTopicId"> <xsl:with-param name="class" select="key(‘classKey’,

&ENDTYPE;/&CLASS;/@xmi.idref)"/> </xsl:call-template> </xsl:variable>

<xtm:topicRef xlink:href="{$topicId}"/> </xtm:member> </xsl:for-each> </xtm:association>

</xsl:if> </xsl:template>

<xsl:template match="&ELEM;/&FC;.Generalization" mode="associations">

<xsl:variable name="subClassId"

select="&SUBTYPE;/&CLASS;/@xmi.idref"/> <xsl:variable name="subClass"

select="key(‘classKey’,$subClassId)"/> <xsl:variable name="superClassId"

select="&SUPERTYPE;/&CLASS;/@xmi.idref"/> <xsl:variable name="superClass"

select="key(‘classKey’,$superClassId)"/>

Если между двумя темами существует отношение обобщения, то используем его как признак канонического отношения superclass-subclass. В спецификации XTM это важное отношение поддержано явно с помощью публикуемых индика­торов предметов (published subject indicators – PSI). В идеале следовало бы опи­раться на отсутствие стереотипа у обобщения, но в той версии XMI, с которой я работал, информации о стереотипах для обобщений вообще нет:

<xsl:if test="(not($subClass/&STEREOTYPE;/@xmi.idref) or

$subClass/&STEREOTYPE;/@xmi.idref = $TOPIC_ID) and

(not($superClass/&STEREOTYPE;/@xmi.idref) or $superClass/&STEREOTYPE;/@xmi.idref = $TOPIC_ID)">

<xtm:association>

<xsl:variable name="id"> <xsl:choose>

<xsl:when test="normalize-space(&NAME;)">

<xsl:value-of select="&NAME;"/> </xsl:when> <xsl:otherwise>

<xsl:value-of select="@xmi.id"/> </xsl:otherwise> </xsl:choose> </xsl:variable>

<xsl:attribute name="id">

<xsl:value-of select="$id"/> </xsl:attribute>

<xtm:instanceOf>

<subjectIndicatorRef

xlink:href="&TM.ORG;#psi-superclass-subclass"/> </xtm:instanceOf>

<xtm:member>

<xtm:roleSpec>

<xtm:subjectIndicatorRef xlink:href="&TM.ORG;#psi-superclass"/> </xtm:roleSpec>

<xsl:variable name="superClassTopicId"> <xsl:call-template name="getTopicId">

<xsl:with-param name="class" select="$superClass"/> </xsl:call-template> </xsl:variable>

<xtm:topicRef xlink:href="{$superClassTopicId}"/>

</xtm:member>

<xtm:member> <xtm:roleSpec>

<xtm:subjectIndicatorRef xlink:href="&TM.ORG;#psi-subclass"/> </xtm:roleSpec>

<xsl:variable name="subClassTopicId"> <xsl:call-template name="getTopicId">

<xsl:with-param name="class" select="$subClass"/> </xsl:call-template> </xsl:variable>

<xtm:topicRef xlink:href="{$subClassTopicId}"/> </xtm:member>

</xtm:association> </xsl:if> </xsl:template>

<xsl:template match="text( )" mode="associations"/> </xsl:stylesheet>

Обсуждение

С помощью тематических карт представляются знания о предметах реального мира. Это позволяет людям и компьютерам находить нужную информацию

точнее и быстрее. Впервые о тематических картах заговорили в 1993 году, ког­да идея была опубликована в рабочем документе Davenport Group1. Затем эта па­радигма была расширена в контексте исследований института GCA Research Institute (ныне называется IDEAlliance) в связи с приложениями стандарта HyTime (http:// www.hytime.org/papers/htguide.html). Спецификация языка XTM была разработа­на как побочный продукт этой работы под контролем независимой организации TopicMaps.org.

Тема (topic) – это электронный аналог предмета (субъекта, subject) реального мира. Оззи Осборн – субъект реального мира, но, поскольку создать реального Оззи в компьютере не получится, то в качестве суррогата мы создаем тему «Оззи». У тем есть имена, которые называются базовыми именами. У каждой темы может быть одно универсальное имя (правильно называть его естественным (unconstrained)) и несколько других, употребляемых в определенных контекстах (scope). Контекстом называется совокупность условий, в которых характеристики тематической карты имеют силу. В нашем примере это может означать, что тема «Оззи Осборн» в юридическом контексте то же самое, что John Michael Osbourne2.

Тема может указывать на вхождение; так называется ресурс, который предостав­ляет относящуюся к теме информацию. Ресурс может ссылаться на адресуемое со­держимое (resourceRef) или сам являться таким содержимым (resourceData).

Тема может принимать участие в специальной ассоциации instanceOf, ко­торая говорит о том, что данная тема является экземпляром более общего класса объектов. Такой класс можно обозначить ссылкой на другую тему или на индика­тор предмета. Индикаторы предметов – интересная особенность тематических карт. Они предлагают способ описания природы предмета посредством ассоции­рования его со стандартным публикуемым адресом, который может, например, устанавливаться государственной организацией.

Темы могут быть связаны ассоциациями. Ассоциация – это именованное отно­шение между двумя или более темами, причем каждая тема играет в ассоциации определенную роль.

Ряд других механизмов, присущих тематических картам, позволяют модели­ровать знания о предметах. Интересующихся читателей отсылаем к специфика­ции XTM по адресу http://www.TopicMaps.org. В сравнении с другими специфи­кациями эта написана в расчете на человека, совсем незнакомого с предметом. Почти вся функциональность XTM отображается на те или иные конструкции UML (как описано в разделе «Решение»). Наибольшую трудность для отображе­ния представляет понятие контекста. В парадигме тематических карт контекст – это способ сообщить, что некоторую характеристику темы следует принимать во внима­ние только в определенных обстоятельствах. Контекст применим к базовым именам, ассоциациям и вхождениям. Хотя сформулированные в решении соглашения позволяют учесть контекст для базовых имен, сделать это для ассоциаций и вхождений пока не удается. Связано это с тем, что соглашения подразумевают моделирование в виде UML-ассоциаций, а в UML ассоциации контекстно незави­симы. Можно было бы смоделировать этот механизм посредством ограничений UML. Но к сожалению та версия XMI, которая реализована в программе Rational Rose, не включает информацию об ограничениях. На практике контекст вообще редко бывает нужен, так что эта проблема, возможно, и не станет помехой, особен­но для начинающих пользователей и составителей тематических карт.

На рис. 13.2 приведен пример тематической карты, представленной в нотации UML. Эта тема моделирует информацию о томатах в контексте еды. Пример, коне­чно, шуточный, но я взял его потому, что Сэм Хантинг приводит такой же пример в своей книге XML Topic Maps: Creating and Using Topic Maps for the Web (Addison Wesley, 2002). На нем он продемонстрировал различные свойства тематических карт, что позволяет проверить точность получившегося в результате XMI-документа. Ниже приведен фрагмент получившегося XTM-файла:

<xtm:topicMap xmlns:xtm=’http://www.topicmaps.org/xtm/1.0′ xmlns:xlink= "http://www.w3.org/1999/xlink"> <xtm:topic id="EN">

<xtm:subjectIdentity>

<xtm:subjectIdicatorRef

xlink:href="http://www.topicmaps.org/xtm/1.0/language.xtm#en"/> </xtm:subjectIdentity> <xtm:baseName>

<xtm:baseNameString>EN</xtm:baseNameString> </xtm:baseName> </xtm:topic> <xtm:topic id="FR">

<xtm:subjectIdentity>

<xtm:subjectIdicatorRef

xlink:href="http://www.topicmaps.org/xtm/1.0/language.xtm#fr"/> </xtm:subjectIdentity> <xtm:baseName>

<xtm:baseNameString>FR</xtm:baseNameString> </xtm:baseName> </xtm:topic>

<xtm:topic id="myTomato"> <xtm:subjectIdentity>

<xtm:subjectIdicatorRef

xlink:href="http://www.fed.gov/usda/doc/tomato.htm#gradeA"/> </xtm:subjectIdentity> <xtm:baseName>

<xtm:baseNameString>tomato</xtm:baseNameString> </xtm:baseName> <xtm:baseName>

Рис. 13.2. UML-диаграмма тематической карты томатов

<xtm:scope>

<xtm:topicRef xlink:href="#EN"/> </xtm:scope>

<xtm:baseNameString>tomato</xtm:baseNameString> </xtm:baseName> <xtm:baseName> <xtm:scope>

<xtm:topicRef xlink:href="#FR"/> </xtm:scope>

<xtm:baseNameString>tomate</xtm:baseNameString> </xtm:baseName> <xtm:variant>

<xtm:variantName>

<xtm:resourceData>TMT</xtm:resourceData> </xtm:variantName> <xtm:parameters>

<xtm:topicRef xlink:href="cell_phone"/> <xtm:topicRef xlink:href="TMT"/> </xtm:parameters> </xtm:variant> <xtm:occurence>

<xtm:resourceRef xlink:href="#tomato.gif"/> </xtm:occurence> </xtm:topic>

<xtm:topic id="myConfite"> <xtm:baseName>

<xtm:baseNameString>tomate confite farcie aux douze saveurs </xtm:baseNameString> </xtm:baseName> <xtm:instanceOf>

<topicRef xlink:href="#desert"/> </xtm:instanceOf> </xtm:topic>

Опущено –>

<xtm:association id="tomato_confite_association"> <xtm:instanceOf>

<topicRef xlink:href="ingredient_of"/> </xtm:instanceOf> <xtm:member>

<xtm:roleSpec>

<xtm:topicRef xlink:href="anIngredient"/> </xtm:roleSpec>

<xtm:topicRef xlink:href="myTomato"/> </xtm:member> <xtm:member>

<xtm:roleSpec>

<xtm:topicRef xlink:href="aDish"/> </xtm:roleSpec>

<xtm:topicRef xlink:href="myConfite"/> </xtm:member> </xtm:association>

<xtm:association id="caramels_confite"> <xtm:instanceOf>

<topicRef xlink:href="ingredient_of"/> </xtm:instanceOf> <xtm:member>

<xtm:roleSpec>

<xtm:topicRef xlink:href="anIngredient"/>

</xtm:roleSpec> <xtm:topicRef xlink:href="myCarmel"/> </xtm:member> <xtm:member>

<xtm:roleSpec>

<xtm:topicRef xlink:href="aDish"/> </xtm:roleSpec>

<xtm:topicRef xlink:href="myConfite"/> </xtm:member> </xtm:association> <!– Опущено –> </xtm:topicMap>

См. также

Стандарты UML и XMI разработаны организацией Object Management Group (OMG). Дополнительную информацию см. на сайтах http://www.omg.org/uml/ и http://www.omg.org/technology/xml/index.htm.

Официальным сайтом, посвященным тематическим картам и языку XTM, яв­ляется TopicMaps.org (http://www.topicmaps.org).

В рецепте 13.5 объясняется, как из тематических карт можно сгенерировать Web-сайт.

Мангано Сэл  XSLT. Сборник рецептов. – М.: ДМК Пресс, СПБ.: БХВ-Петербург, 2008. – 864 с.: ил.

По теме:

  • Комментарии