Вложенная обработка XML с помощью XSLT - PullRequest
2 голосов
/ 19 августа 2011

У меня есть документ XML со следующей структурой:

  • корневой элемент DataModel может иметь дочерние элементы Node, Integer и String
  • Элемент Node также может иметь дочерние элементы Node, Integer и String

например:.

<DataModel>
  <String name="a">aaa</String>
  <Integer name="b">bbb</Integer>
  <Node name="n1">
   <String name="k">kkk</String>
    <Integer name="l">lll</Integer>
    <Node name="n2">
      <String name="x">xxx</String>
    </Node>
  </Node>
</DataModel>

Я бы хотел обработать этот XML, сгладив вывод, но приведя иерархическую структуру в именовании, например:

<table>
  <tr>
    <th>Name</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>a</td>
    <td>aaa</td>
  </tr>
  <tr>
    <td>b</td>
    <td>bbb</td>
  </tr>
  <tr>
    <td>n1.k</td>
    <td>kkk</td>
  </tr>
  <tr>
    <td>n1.l</td>
    <td>lll</td>
  </tr>
  <tr>
    <td>n1.n2.x</td>
    <td>xxx</td>
  </tr>
</table>

Есть идеи, как это сделать?

Ответы [ 2 ]

0 голосов
/ 19 августа 2011

Этот шаблон поддерживает любую глубину вложенности, благодаря для каждого с предком :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml"/>

    <xsl:template match="DataModel">
        <table>
            <tr>
                <th>Name</th>
                <th>Description</th>
            </tr>


            <xsl:apply-templates select="*"/>
        </table>
    </xsl:template>

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

    <xsl:template match="String|Integer">
        <tr>
            <td>
                <xsl:for-each select="ancestor::Node">
                    <xsl:value-of select="concat(@name, '.')"/>
                </xsl:for-each>
                <xsl:value-of select="@name"/>
            </td>
            <td>
                <xsl:value-of select="."/>
            </td>
        </tr>
        <xsl:apply-templates select="*"/>
    </xsl:template>

</xsl:stylesheet>

так что результат в точности соответствует требуемому, включая последнюю строку:

...
  <tr>
    <td>n1.n2.x</td>
    <td>xxx</td>
  </tr>
</table>
0 голосов
/ 19 августа 2011

Используйте этот шаблон:

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

    <xsl:template match="DataModel">
        <table>
            <tr>
                <th>Name</th>
                <th>Description</th>
            </tr>


            <xsl:apply-templates select="*"/>
        </table>
    </xsl:template>

    <xsl:template match="*">

        <tr>
            <td>
                <xsl:for-each select="ancestor::Node">
                    <xsl:value-of select="concat(@name, '.')"/>
                </xsl:for-each>

                <xsl:value-of select="@name"/>
            </td>
            <td>
                <xsl:value-of select="."/>
            </td>
        </tr>

        <xsl:apply-templates select="*"/>
    </xsl:template>

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

</xsl:stylesheet>

Применительно к XML:

<DataModel>
    <String name="a">aaa</String>
    <Integer name="b">bbb</Integer>
    <Node name="n1">
        <String name="k">kkk</String>
        <Integer name="l">lll</Integer>
        <Node name="n2">
            <String name="x">xxx</String>
        </Node>
    </Node>
</DataModel>

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

<table>
    <tr>
        <th>Name</th>
        <th>Description</th>
    </tr>
    <tr>
        <td>a</td>
        <td>aaa</td>
    </tr>
    <tr>
        <td>b</td>
        <td>bbb</td>
    </tr>
    <tr>
        <td>n1.k</td>
        <td>kkk</td>
    </tr>
    <tr>
        <td>n1.l</td>
        <td>lll</td>
    </tr>

    <tr>
        <td>n1.n2.x</td>
        <td>xxx</td>
    </tr>

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