автоматическое создание шаблона xml на основе строкового шаблона с использованием XSLT - PullRequest
1 голос
/ 23 декабря 2011

У меня есть строка в шаблоне ниже

автор ~ раз ~ ~ assignedAuthor assignedAuthor / идентификатор ~ assignedAuthor / адр ~ assignedAuthor / телеком ~ assignedAuthor / assignedPerson / имя ~

Все время первый элемент является корневым (в приведенном выше строковом шаблоне это author ), а остальные являются дочерними элементами, удаленными символом '~'. Я хотел бы создать XML с использованием XSLT 2.0, используя вышеуказанный строковый шаблон, и я хочу создать ниже XML.

<author>
    <time/>
    <assignedAuthor>
        <id/>
        <addr/>
        <telecom/>
        <assignedPerson>
            <name/>
        </assignedPerson>
    </assignedAuthor>
</author>

Могу ли я найти возможные решения для этого.

1 Ответ

3 голосов
/ 24 декабря 2011

Это преобразование :

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:my="my:my" exclude-result-prefixes="my xs">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vSegments" select=
  "tokenize(translate(/*, ' &#9;&#xA;&#xD;', ''),
            '~')
               [.]
  "/>

  <xsl:template match="/*">
   <xsl:sequence select="my:buildXml($vSegments)"/>
  </xsl:template>

 <xsl:function name="my:buildXml">
  <xsl:param name="pSegments" as="xs:string*"/>

  <xsl:element name="{$pSegments[1]}">
    <xsl:sequence select="my:buildXml2($pSegments[position() >1])"/>
  </xsl:element>
 </xsl:function>

 <xsl:function name="my:buildXml2">
  <xsl:param name="pSegments" as="xs:string*"/>

  <xsl:for-each-group select="$pSegments"
       group-adjacent="substring-before(concat(.,'/'),'/')">
    <xsl:element name="{current-grouping-key()}">
      <xsl:variable name="vsubSegments" select=
        "for $subSeg in current-group(),
             $subSeqTail in substring-after($subSeg, '/')
          return
             $subSeqTail[.]
        "/>
      <xsl:sequence select=
         "my:buildXml2($vsubSegments)"/>
    </xsl:element>
  </xsl:for-each-group>
 </xsl:function>
</xsl:stylesheet>

при применении к следующему XML-документу (используя немного более сложную строку, чтобы сделать это еще более сложным):

<t>
author
   ~time
   ~assignedAuthor
   ~assignedAuthor/id
   ~assignedAuthor/addr
   ~assignedAuthor/telecom
   ~assignedAuthor/assignedPerson/name
   ~assignedAuthor/assignedPerson/address~
</t>

дает желаемый, правильный результат :

<author>
   <time/>
   <assignedAuthor>
      <id/>
      <addr/>
      <telecom/>
      <assignedPerson>
         <name/>
         <address/>
      </assignedPerson>
   </assignedAuthor>
</author>

Объяснение :

  1. Токенизация последовательности «сегментов». Использование tokenize().

  2. Группировка (xsl:for-each-group) с атрибутом group-adjacent с использованием в качестве ключа группировки первого «подсегмента».

  3. Для каждой группы, которая рекурсивно строит поддерево XML. Использование current-grouping-key() и current-group()

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