XSLT Универсальное преобразование структурного типа значения в однозначную строку - PullRequest
0 голосов
/ 17 октября 2019

Я хочу создать xslt-преобразование, которое преобразует структурный атрибут в однозначную строку и предпочтительно является универсальным, поэтому нет ссылки на именованные элементы из входных данных.

Пример ввода:

<attr attr-name="items">
        <value type="structured">
          <component name="studentnummer">001001</component>
          <component name="achternaam">Bimans</component>
          <component name="voorletters">L./component>
          <component name="roepnaam">Leo</component>
          <component name="geboortedatum">09-08-1986</component>
          <component name="geslacht">V</component>
          <component name="mobiel_telefoonnummer">0612345678</component>
          <component name="voertaal_nl">Nederlands</component>
          <component name="voertaal_en">Dutch</component>
          <component name="extern_emailadres">L.Bimans@domain.nl</component>
        </value>
        <value type="structured">
          <component name="studentnummer">001002</component>
          <component name="achternaam">Boels</component>
          <component name="voorletters">F.</component>
          <component name="roepnaam">Felix</component>
          <component name="geboortedatum">04-02-1993</component>
          <component name="geslacht">M</component>
          <component name="voertaal_nl">Nederlands</component>
          <component name="voertaal_en">Dutch</component>
        </value>
</attr>

Должен быть переведен на:

<attr attr-name="items">
    <value type="string">#studentnummer#001001#achternaam#Bimans#voorletters#L.#roepnaam#Leo#geboortedatum#09-08-1986#geslacht#V#mobiel_telefoonnummer#0612345678#voertaal_nl#Nederlands#voertaal_en#Dutch#extern_emailadres#L.Bimans@domain.nl></value>
    <value type="string">#studentnummer#001002#achternaam#Boels#voorletters#F.#roepnaam#Felix#geboortedatum#04-02-1993#geslacht#M#voertaal_nl#Nederlands#voertaal_en#Dutch</value>
<attr>

Другой пример:

<attr attr-name="links">
        <value type="structured">
          <component name="rel">self</component>
          <component name="href">http://192.83.206.98:9999/rds/basis/studenten/</component>
        </value>
        <value type="structured">
          <component name="rel">edit</component>
          <component name="href">http://192.83.206.98:9999/rds/basis/studenten/</component>
        </value>
        <value type="structured">
          <component name="rel">describedby</component>
          <component name="href">http://192.83.206.98:9999/rds/metadata-catalog/basis/studenten/</component>
        </value>
</attr>

Должен быть переведен на:

<attr attr-name="links">
    <value type="string">#rel#self#href#http://192.83.206.98:9999/rds/basis/studenten/</value>
    <value type="string">#rel#edit#href#http://192.83.206.98:9999/rds/basis/studenten/</value>
    <value type="string">#rel#describedby#href#http://192.83.206.98:9999/rds/metadata-catalog/basis/studenten/</value>
</attr>

Преобразование должно быть как можно более общим. Другими словами, один и тот же код может использоваться для обоих типов входных данных (если это возможно). Так что никаких ссылок на имена атрибутов, значения или что бы то ни было. Обратите внимание, что имя компонента (из структурного) должно (предпочтительно) быть включено в результирующую строку (как показывают примеры), и после него должно следовать фактическое значение (все разделены символом-разделителем #).

Я пытался сделать это, но пока не получалось.

Также обратите внимание, что я могу использовать только xslt 1.0!

Спасибо!

Ответы [ 2 ]

0 голосов
/ 17 октября 2019

Поскольку вы не хотите иметь имена элементов и атрибутов, возникает вопрос: «Как мы хотим идентифицировать узлы (как элементы, так и атрибуты), которые содержат наши значения?»

Единственное другоея знаю о том, что можно предположить фиксированные положения узлов в исходных деревьях.

Это делает следующий XSLT, пока структура остается:

attr
  value
    component
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:output 
        method="xml"
        indent="yes"/>

    <xsl:template match="/">
        <xsl:apply-templates/> 
    </xsl:template>


    <!-- node()[self::*] tests for an element node-type, 
         thus we only process element nodes, this way -->
    <xsl:template match="/node()[self::*]">
        <!-- we create a new element, that has its name set 
             to the name of the current node, indicated by '.' -->
        <xsl:element name="{name(.)}">
            <!-- We now create an attribute for the element we are creating.
                 Handling the attribute like this is only going 
                 to work out the way we want it, if the attribute,
                 whose  name we want to replicate is the first attribute 
                 of the element. -->
            <xsl:attribute name="{name(attribute::node())}">
                <xsl:value-of select="attribute::node()"/>
            </xsl:attribute>
            <!-- within our current node (which is 'attr') we iterate 
                 through each contained node and create an output element, which will
                 be the 'value' element. -->
            <xsl:for-each select="node()[self::*]">
                <xsl:element name="{name(.)}">
                    <xsl:attribute name="type">string</xsl:attribute>
                    <!-- within each 'value' element, we iterate through all 'component'
                         elements, constructing out text node dynamically. -->
                    <xsl:for-each select="node()[self::*]">
                        <xsl:text>#</xsl:text>
                        <xsl:value-of select="attribute::node()"/>
                        <xsl:text>#</xsl:text>
                        <xsl:value-of select="."/>
                    </xsl:for-each>
                </xsl:element>
            </xsl:for-each>
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

    <!-- we suppress any built-in templates for text-node processing, otherwise we
         would get them in the output, too. -->
    <xsl:template match="text()"/>

</xsl:stylesheet>

PS Я не знаю, почему вы ограничены в использовании XSLT-1.0, но вы также можете получить программу Saxon от http://saxonica.com. SaxonHE (см. Материалы для загрузки) с открытым исходным кодом и бесплатным для использования.

0 голосов
/ 17 октября 2019

Чтобы сделать это в общем, я сначала начал бы с идентификатора, чтобы скопировать существующий XML:

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

Затем имел бы шаблон, который соответствует любым элементам, которые имеют атрибут type="structured" (т.е. все ваше значениеэлементы). Для совпадающих мы скопируем элемент и добавим атрибут type="string". И мы установим текст этого элемента, состоящий из ##, плюс значение атрибута name и текст каждого дочернего элемента. Например:

<xsl:template match="*[@type = 'structured']">
  <xsl:copy>
    <xsl:attribute name="type">string</xsl:attribute>
    <xsl:for-each select="*">##<xsl:value-of select="@name" />##<xsl:value-of select="text()" /></xsl:for-each>
  </xsl:copy>
</xsl:template>

Это достаточно универсально, чтобы все, что вам действительно нужно, это узел с type="structure" и дочерние элементы с атрибутом имени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...