Как я могу использовать XSLT 1.0 для добавления структуры в не-иерархический XML-файл? - PullRequest
1 голос
/ 02 апреля 2012

У меня есть не-heirarchal xml, который имеет псевдоструктуру.Каждый объект объявляет родителя (кроме «корневого» объекта) и ноль или более потомков, но делает это, используя идентификаторы и ссылочные атрибуты, а не вложенную структуру.Я хотел бы преобразовать это во вложенную структуру.

<document>
    <object id="6" children="12,15"/>
    <object id="12" parent="6" children="13,18"/>
    <object id="13" parent="12" children="14,16,17"/>
    <object id="14" parent="13"/>
    <object id="15" parent="6" children="21,22"/>
    <object id="16" parent="13"/>
    <object id="17" parent="13"/>
    <object id="18" parent="12" children="23,25"/>
    <object id="19" parent="23"/>
    <object id="21" parent="15"/>
    <object id="22" parent="15"/>
    <object id="23" parent="18" children="19,24"/>
    <object id="24" parent="23"/>
    <object id="25" parent="18"/>
</document>

Для записи фактический документ также содержит определения объектов, на которые объекты также ссылаются в атрибуте, похожем на класс, но мне нужно получитьимя элемента из определения, опять же, по ссылочному идентификатору.В какой-то момент процесса я конвертирую имена каждого «объекта» в «шаблон» или «подраздел».Если это упрощает вещи, я могу выполнить эту операцию после применения структуры.У меня также есть токенизированная «функция» для атрибута children, так как я использую XSLT 1.0, который не имеет его встроенного.

Так что для примера выше я хотел бы получить такой вывод:

<document>
    <object id="6">
        <object id="12">
            <object id="13">
                <object id="14"/>
                <object id="16"/>
                <object id="17"/>
            </object>
            <object id="18">
                <object id="23">
                    <object id="19"/>
                    <object id="24"/>
                </object>
                <object id="25"/>
            </object>
        </object>
        <object id="15">
            <object id="21"/>
            <object id="22"/>
        </object>
    </object>
</document>

Имейте в виду, что эти элементы объекта содержат другую информацию, атрибуты, данные и т. Д. Они были удалены, чтобы упростить пример, но могут добавить сложность к проблеме.

Если возможно, я хотел бы сделать это элегантным и расширяемым способом.Я не обязан, но предпочел бы использовать XSL 1.0 (чтобы его можно было интегрировать с существующим серверным программным обеспечением).

Спасибо всем, кто может мне помочь или указать мне правильное направление!

Ответы [ 2 ]

0 голосов
/ 03 апреля 2012

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

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kChildren" match="object" use="@parent"/>

 <xsl:template match="/*">
   <document>
     <xsl:apply-templates select="*[not(@parent)]"/>
   </document>
 </xsl:template>

 <xsl:template match="object">
  <object id="{@id}">
    <xsl:apply-templates select="key('kChildren', @id)"/>
  </object>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<document>
    <object id="6" children="12,15"/>
    <object id="12" parent="6" children="13,18"/>
    <object id="13" parent="12" children="14,16,17"/>
    <object id="14" parent="13"/>
    <object id="15" parent="6" children="21,22"/>
    <object id="16" parent="13"/>
    <object id="17" parent="13"/>
    <object id="18" parent="12" children="23,25"/>
    <object id="19" parent="23"/>
    <object id="21" parent="15"/>
    <object id="22" parent="15"/>
    <object id="23" parent="18" children="19,24"/>
    <object id="24" parent="23"/>
    <object id="25" parent="18"/>
</document>

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

<document>
    <object id="6">
        <object id="12">
            <object id="13">
                <object id="14"/>
                <object id="16"/>
                <object id="17"/>
            </object>
            <object id="18">
                <object id="23">
                    <object id="19"/>
                    <object id="24"/>
                </object>
                <object id="25"/>
            </object>
        </object>
        <object id="15">
            <object id="21"/>
            <object id="22"/>
        </object>
    </object>
</document>

Пояснение : правильное использование ключей.

0 голосов
/ 02 апреля 2012

Не выполняя полный XSLT, вы могли бы структурировать свое преобразование, как показано ниже: в основном, шаблон для книг будет вызывать apply-шаблоны для глав, а шаблон для глав будет применять шаблоны для тем и т. Д. Ключевым моментом здесь является помещение идентификатора родителя в переменную, чтобы вы могли использовать его в последующих вызовах apply-template для поиска дочерних элементов.

<document>
   <xsl:apply-templates select="/document/book" />
</document>

<xsl:template match="/document/book">
   <xsl:variable name="bookid">
      <xsl:value-of select="@id"/>
   </xsl:variable>
   <xsl:element name="book">
      <xsl:attribute name="id">
         <xsl:value-of select="@id"/>
      </xsl:attribute>
      <xsl:apply-templates select="/document/chapter[@parent=$bookid]" />
   </xsl:element>
</xsl:template>

<xsl:template match="/document/chapter">
   Template for chapter would be replicated from the book template above
   .
   .
   .
</xsl:template>
...