通用xslt转换不同大小的XML

时间:2015-08-24 09:51:22

标签: xml generics xslt

抱歉,我是XSLT的新手,并且在创建非常通用的模板以生成结果HTML时遇到问题。如果没有您在下面看到的示例代码,我不知道如何更简单地解释它:

这是带有虚拟数据的XML,重要的是我有许多标签/子项,如<Test_Info><Dataroot>的子项)。但它们与<Test_Info>具有相同的结构。所以大部分第3 <Element>都包含重要的结果。问题是从文件到文件我可以有3个结果(如Result3,Result4,Result6),在另一个文件中我可以有30个(Result1,Result4,Result [N] ...)。

我希望我能够很好地理解我的问题

抱歉我的英语我不是本地的说话人

编辑: 感谢michael.hor257k它适用于此部分(Test_Info),但当我添加另一个而不是它生成垃圾。我扩展了我的XML示例以解释我的进一步问题:

<?xml-stylesheet version='1.0' encoding='ISO 8859-1'?>
<Dataroot>
  <Test_Info>
    <Element>
        <Signal/>
        <Monitor/>
        <Data>
            <Type/>
            <Result3/>
            <Result4/>
            <Result6/>
        </Data>
    </Element>
    <Element>
        <Signal>Test</Signal>
        <Monitor>-</Monitor>
        <Data>
            <Type>Name</Type>
            <Result3>-</Result3>
            <Result4>-</Result4>
            <Result6>-</Result6>
        </Data>
        <Data>
            <Type>Test_Detail</Type>
            <Result3>pre</Result3>
            <Result4>pulse</Result4>
            <Result6>post</Result6>
        </Data>
        <Data>
            <Type>GlobalErr_Count</Type>
            <Result3>0</Result3>
            <Result4>6</Result4>
            <Result6>0</Result6>
        </Data>
    </Element>
  </Test_Info>
  <Test_1>
    <Element>
        <Signal/>
        <Monitor/>
        <Data>
            <Type/>
            <Result3/>
            <Result4/>
            <Result6/>
        </Data>
    </Element>
    <Element>
        <Signal>Systemtime</Signal>
        <Monitor/>
        <Data>
            <Type>Stamp</Type>
            <Result3>01.01.1999 14:52:00</Result3>
            <Result4>01.01.1999 14:52:50</Result4>
            <Result6>01.01.1999 14:53:26</Result6>
        </Data>
    </Element>
    <Element>
        <Signal>Signal1</Signal>
        <Monitor>0</Monitor>
        <Data>
            <Type>Testphase</Type>
            <Result3>pre</Result3>
            <Result4>pulse</Result4>
            <Result6>post</Result6>
        </Data>
        <Data>
            <Type>ERR_Value</Type>
            <Result3>xxx</Result3>
            <Result4>xxx</Result4>
            <Result6>xxx</Result6>
        </Data>
        <Data>
            <Type>ERR_Volt</Type>
            <Result3>yyy</Result3>
            <Result4>yyy</Result4>
            <Result6>yyy</Result6>
        </Data>
        <Data>
            <Type>ERR_Timestamp</Type>
            <Result3>65535</Result3>
            <Result4>65535</Result4>
            <Result6>65535</Result6>
        </Data>
        <Data>
            <Type>ERR_CNT</Type>
            <Result3>255</Result3>
            <Result4>255</Result4>
            <Result6>255</Result6>
        </Data>
        <Data>
            <Type>MIN_Volt</Type>
            <Result3>aaa</Result3>
            <Result4>aaa</Result4>
            <Result6>aaa</Result6>
        </Data>
        <Data>
            <Type>Max_Volt</Type>
            <Result3>zzz</Result3>
            <Result4>zzz</Result4>
            <Result6>zzz</Result6>
        </Data>
        <Data>
            <Type>MinMax_Timestamp</Type>
            <Result3>65535</Result3>
            <Result4>65535</Result4>
            <Result6>65535</Result6>
        </Data>
    </Element>
    <Element>
        <Signal>Signal2</Signal>
        <Monitor>1</Monitor>
        <Data>
            <Type>Testphase</Type>
            <Result4>pulse</Result4>
        </Data>
        <Data>
            <Type>ERR_Value</Type>
            <Result4>FFFF</Result4>
        </Data>
        <Data>
            <Type>ERR_Volt</Type>
            <Result4>yyy</Result4>
        </Data>
        <Data>
            <Type>ERR_Timestamp</Type>
            <Result4>65535</Result4>
        </Data>
        <Data>
            <Type>ERR_CNT</Type>
            <Result4>255</Result4>
        </Data>
        <Data>
            <Type>MIN_Volt</Type>
            <Result4>aaa</Result4>
        </Data>
        <Data>
            <Type>Max_Volt</Type>
            <Result4>ddd</Result4>
        </Data>
        <Data>
            <Type>MinMax_Timestamp</Type>
            <Result4>65535</Result4>
        </Data>
    </Element>
    </Test_1>
    <Test_2>
        always the same structure as <Test_Info>
    </Test_2>
    <Test_N>
        always the same structure as <Test_Info>
    </Test_N>
</Dataroot>

它必须如下所示: http://i.stack.imgur.com/hsDl4.png

顺便说一下:谢谢大家,它已经比以前更好了

2 个答案:

答案 0 :(得分:1)

您可以做的是,在选择xsl:for-each节点的节点中有另一个Element,该节点仅选择第一个Result元素的Data元素,如这些对应于每行的第一个单元格。

<xsl:for-each select="Data[1]/*[starts-with(local-name(), 'Result')]">

然后你就可以得到构成行的元素:

<xsl:for-each select="../../Data/*[local-name() = local-name(current())]">

使用表达式../..是因为您当前位于Result元素上,并且您需要返回到Element元素然后转到所有其他节点。虽然最好在变量中存储对父Element节点的引用。

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="Test_Info">
    <h3>
        <xsl:value-of select="local-name()"/>
    </h3>
    <table>
        <tr>
            <th style="border: 1px solid #000000;text-align:center"/>
            <th style="border: 1px solid #000000;text-align:center"/>
            <th style="border: 1px solid #000000;text-align:center"/>
            <th style="border: 1px solid #000000;text-align:center">Test Detail</th>
            <th style="border: 1px solid #000000;text-align:center">Global Error Count</th>
        </tr>
        <xsl:for-each select="/Dataroot/Test_Info/Element">
            <xsl:variable name="Element" select="." />
            <xsl:for-each select="Data[1]/*[starts-with(local-name(), 'Result')]">
                <tr>
                    <td style="border: 1px solid #000000;text-align:center"/>
                    <td style="border: 1px solid #000000;text-align:center"/>
                    <xsl:for-each select="$Element/Data/*[local-name() = local-name(current())]">
                        <td style="border: 1px solid #000000;text-align:center">
                            <xsl:value-of select="."/>
                        </td>
                    </xsl:for-each>
                </tr>
            </xsl:for-each>
        </xsl:for-each>
    </table>
</xsl:template>
</xsl:stylesheet>

答案 1 :(得分:0)

很难理解你的例子中给出了什么,只是一个例子。

假设(除其他事项外)第一个Element包含表结构,而第二个Element包含所有数据,您可以这样:

XSLT 1.0

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

<xsl:template match="/Dataroot">
    <h3>
        <xsl:value-of select="name(*)"/>
    </h3>
    <xsl:variable name="data" select="*/Element[2]/Data" />
    <table border="1">
        <thead>
            <tr>
                <xsl:for-each select="$data">
                    <th><xsl:value-of select="Type"/></th> 
                </xsl:for-each>       
            </tr>
        </thead>
        <tbody>
            <xsl:for-each select="*/Element[1]/Data[1]/*[not(self::Type)]">
            <xsl:variable name="i" select="position()" />
                <tr>
                    <xsl:for-each select="$data">
                        <td><xsl:value-of select="*[not(self::Type)][$i]"/></td> 
                    </xsl:for-each>       
                </tr>
            </xsl:for-each>       
        </tbody>
    </table>
</xsl:template>

</xsl:stylesheet>

应用于您的示例时的结果(呈现)将为:

enter image description here