简体   繁体   English

XSLT用于动态嵌套XML表

[英]XSLT for dynamic nested XML tables

I am new to xslt and facing a problem as I have generated an xml file dynamically (ie node names are unknown) And tried many approaches to view the content in nested tables in html file using xslt, but all my efforts are failing. 我是xslt的新手,由于动态生成了一个xml文件(即节点名称未知),因此遇到了一个问题,并尝试了许多使用xslt来查看html文件中嵌套表中内容的方法,但是我的所有努力都失败了。

<?xml version="1.0" encoding="UTF-8"?>
<content>
    <Source>
        <Column1>Name</Column1>
        <Column2>Organization Name</Column2>
        <SubSource>
            <Column1>Name</Column1>
            <Column2>Person Name</Column2>
            <Column1>Address</Column1>
            <Column2>House: E5, Block-G, Road-02</Column2>
            <Details>
                <Column1>Entry date</Column1>
                <Column2>6/6/13 12:04 PM</Column2>
                <Column1>height</Column1>
                <Column2>153</Column2>
                <Column1>weight</Column1>
                <Column2>53.5</Column2>
                <Column1>temperature</Column1>
                <Column2>98.67</Column2>
                <Column1>pulse rate</Column1>
                <Column2>76</Column2>
                <Advices>
                    <Advice>
                        <Column1>Title</Column1>
                        <Column2>Workout</Column2>
                        <Column1>Location</Column1>
                        <Column2>In the Park</Column2>
                    </Advice>
                    <Advice>
                        <Column1>Title</Column1>
                        <Column2>Eating Habit</Column2>
                        <Column1>Remarks</Column1>
                        <Column2>Eat Less</Column2>
                        <Column1>Notes</Column1>
                        <Column2>Avoid salts</Column2>
                    </Advice>
                </Advices>
            </Details>
        </SubSource>
    </Source>
    <Source>
        <Column1>Name</Column1>
        <Column2>Organization Name</Column2>
        <SubSource>
            <Column1>Name</Column1>
            <Column2>Person Name</Column2>
            <Column1>Address</Column1>
            <Column2>House: E5, Block-G, Road-02</Column2>
            <Details>
                <Column1>Entry date</Column1>
                <Column2>6/6/13 12:04 PM</Column2>
                <Column1>height</Column1>
                <Column2>153</Column2>
                <Column1>weight</Column1>
                <Column2>53.5</Column2>
                <Column1>temperature</Column1>
                <Column2>98.67</Column2>
                <Column1>pulse rate</Column1>
                <Column2>76</Column2>
                <Advices>
                    <Advice>
                        <Column1>Title</Column1>
                        <Column2>Workout</Column2>
                        <Column1>Location</Column1>
                        <Column2>In the Park</Column2>
                    </Advice>
                </Advices>
            </Details>
        </SubSource>
    </Source>
</content>

I have used few xslt approaches. 我使用了几种xslt方法。 However all of them not viewing the data as wanted, either less or not in properly format table!!! 但是他们所有人都没有按照需要查看数据,无论是少于还是没有按照正确格式的表格查看!!!

The following was my best approach (I didn't do the multiple tables design as I wanted to get all data first) 以下是我最好的方法(我没有做多表设计,因为我想先获取所有数据)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html"/>
    <xsl:template match="/">
        <html>
            <body>
                <table>
                    <xsl:apply-templates select="content/Source"/>
                </table>
            </body>
        </html>
    </xsl:template>
    <xsl:template match="content/Source">
        <xsl:variable name="column" select="content/Source"/>
        <tr>
            <td>
                <xsl:value-of select="Column1"/>
            </td>
            <td>
                <xsl:value-of select="Column2"/>
            </td>
        </tr>
        <xsl:apply-templates select="SubSource"/>
    </xsl:template>
    <xsl:template match="SubSource">
        <tr>
            <td>
                <xsl:value-of select="Column1"/>
            </td>
            <td>
                <xsl:value-of select="Column2"/>
            </td>
        </tr>
        <xsl:apply-templates select="Details"/>
    </xsl:template>
    <xsl:template match="Details">
        <tr>
            <td>
                <xsl:value-of select="Column1"/>
            </td>
            <td>
                <xsl:value-of select="Column2"/>
            </td>
        </tr>
        <xsl:apply-templates select="Advices"/>
    </xsl:template>
    <xsl:template match="Advices">
        <xsl:for-each select="Advice">
            <tr>
                <td>
                    <xsl:value-of select="Column1"/>
                </td>
                <td>
                    <xsl:value-of select="Column2"/>
                </td>
            </tr>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

And the output is: 输出为:

 <table>
         <tr>
            <td>Name</td>
            <td>Organization Name</td>
         </tr>
         <tr>
            <td>Name</td>
            <td>Person Name</td>
         </tr>
         <tr>
            <td>Entry date</td>
            <td>6/6/13 12:04 PM</td>
         </tr>
         <tr>
            <td>Title</td>
            <td>Workout</td>
         </tr>
         <tr>
            <td>Title</td>
            <td>Eating Habit</td>
         </tr>
         <tr>
            <td>Name</td>
            <td>Organization Name</td>
         </tr>
         <tr>
            <td>Name</td>
            <td>Person Name</td>
         </tr>
         <tr>
            <td>Entry date</td>
            <td>6/6/13 12:04 PM</td>
         </tr>
         <tr>
            <td>Title</td>
            <td>Workout</td>
         </tr>
      </table>

My target is to get get table layout same as the XML structured. 我的目标是获取与XML结构相同的表布局。

Advices for better XML format are always welcomed! 始终欢迎获得更好的XML格式的建议!

Thank you 谢谢

This XSLT 1.0 stylesheet does what you seem to want: It creates nested HTML tables from a structure of unknown element names. 这个XSLT 1.0样式表完成了您似乎想要的工作:它从未知元素名称的结构创建嵌套的HTML表。

I the only prerequisite is that there are <Column1> elements that are possibly followed by an associated <Column2> . 我唯一的先决条件是存在<Column1>元素,之后可能是关联的<Column2>

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

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

  <!-- #1: anything that has <Column1> children becomes a table -->
  <xsl:template match="*[Column1]">
    <table class="{name()}">
      <xsl:apply-templates select="*" mode="nested" />
    </table>
  </xsl:template>

  <!-- #2: ...if it's nested, it is wrapped in a table row first -->
  <xsl:template match="*[Column1]" mode="nested">
    <tr>
      <td colspan="2">
        <!-- this actually executes #1 because it uses no mode! -->
        <xsl:apply-templates select="." />
      </td>
    </tr>
  </xsl:template>

  <!-- #3: <Column1> governs the creation of table rows -->
  <xsl:template match="*[Column1]/Column1" mode="nested">
    <tr>
      <td><xsl:value-of select="." /></td>
      <td><xsl:value-of select="following-sibling::*[1][self::Column2]" /></td>
    </tr>
  </xsl:template>

  <!-- #4: suppress any other data field (like <Column2>) -->
  <xsl:template match="*[Column1]/*[not(*)]" mode="nested" />

</xsl:stylesheet>

Note the use of template modes: If there is more than one template that can match a certain element, you can use mode to differentiate between them. 请注意模板模式的使用:如果有多个模板可以与某个元素匹配,则可以使用mode来区分它们。

In this case, you want to create nested tables. 在这种情况下,您要创建嵌套表。 At the root level (the default case), you can simply create a <table> element. 在根级别(默认情况),您可以简单地创建一个<table>元素。

Hovever, if you already are inside a <table> , you must create a <tr> / <td> first, but after that the process is the same. 但是,如果您已经在<table> ,则必须先创建<tr> / <td> ,但是此后的过程是相同的。

By using modes I can make sure that the right template is executed in the right context without having to repeat myself when it comes to creating the actual <table> . 通过使用模式,我可以确保在正确的上下文中执行正确的模板,而不必在创建实际的<table>时重复自己。

As a side effect, by using modes we could create a whole set of templates that can be dropped into an existing stylesheet without affecting the established workflow. 副作用是,通过使用模式,我们可以创建一整套模板,可以将该模板放到现有样式表中,而不会影响已建立的工作流程。


following-sibling::*[1][self::Column2] is "The first following sibling, but only if it actually is a <Column2> ." following-sibling::*[1][self::Column2]“第一个后继兄弟姐妹,但<Column2>是它实际上是<Column2> 。” .


The template #4 is necessary since the rather unspecific <xsl:apply-templates select="*" mode="nested" /> also applies to <Column2> . 模板#4是必需的,因为不太明确的<xsl:apply-templates select="*" mode="nested" />也适用于<Column2> However, those are actually already handled by #3, which means unless we explicitly suppress them they would generate unwanted duplicate output. 但是,这些实际上已经由#3处理,这意味着,除非我们明确禁止它们,否则它们将生成不需要的重复输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM