使用XLST 1.0将XML转换为唯一嵌套XML

时间:2015-06-08 00:22:37

标签: xml xslt filemaker

我正在尝试将filemaker数据库导出的输出转换为Web应用程序可用的表单。我试图写一个XLST(1.0)进行转换。 Filemaker输出本质上是一个电子表格(行x列),我想根据关系转换它。基本上对于每个坦克“Col [1]”我想要在某个日期收集的数据“Col [2]”与此“Col [3]”相关联。

使用XSLT,我已经能够获得独特的日期或独特的坦克,但不是每个坦克的多个日期。

我已经包含了我的XLST,以及输入XML看起来像的“简化”版本,以及我希望得到的内容。

非常感谢任何建议!

XLST到目前为止

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fmp="http://www.filemaker.com/fmpxmlresult" version="1.0" exclude-result-prefixes="fmp">
<xsl:output method="xml" version="1.0" encoding="windows-1251" indent="yes"/>

<xsl:key name="fishdate" match="fmp:ROW" use="fmp:COL[3]"/>
<xsl:key name="tanknumber" match="fmp:ROW" use="fmp:COL[9]"/>

<xsl:template match="/">
    <fishroom>
        <xsl:for-each select="fmp:FMPXMLRESULT/fmp:RESULTSET/fmp:ROW[generate-id()=generate-id(key('tanknumber',fmp:COL[9]))]">

                <!-- <xsl:for-each select="fmp:FMPXMLRESULT/fmp:RESULTSET/fmp:ROW[generate-id()=generate-id(key('fishdate',fmp:COL[3]))]"> -->
                        <date> <xsl:value-of select="fmp:COL[3]/fmp:DATA"/>
                            <tank> 
                                <temp><xsl:value-of select="fmp:COL[10]/fmp:DATA"/></temp>
                            </tank>
                        </date>
                 <!-- </xsl:for-each> -->
        </xsl:for-each>

    </fishroom>
</xsl:template>
</xsl:stylesheet>

输入XML:

<row>
    <col>1/1/14</col>
    <col>tank1</col>
    <col>data1</col
</row>
<row>
    <col>1/1/14</col>
    <col>tank2</col>
    <col>data3</col>
</row>
<row>
    <col>1/2/14</col>
    <col>tank1</col>
    <col>data2</col>
</row>

期望输出:

<tank1>
    <date>1/1/14
         <somedata>data2</somedata>
    </date>
    <date>1/2/14
         <somedata>data1</somedata>
   </date>
</tank1>
<tank2>
     <date>1/2/14
         <somedata>data3</somedata>
      </date>
</tank2>

1 个答案:

答案 0 :(得分:1)

您的尝试有几个问题,最严重的问题是:

  1. 'fishdate'密钥必须使用tankdate的串联。 否则,您将在每个记录下对所有记录进行子分组 tank;
  2. tank分组后,您必须继续并对记录进行分组 在当前群组中。这些可以通过用于确定不同坦克的相同键来访问。
  3. 您遗漏了实际列出每个数据的第三步 子组。
  4. 给出以下示例输入:

    <强> XML

    <FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
        <!-- omitted -->
        <RESULTSET FOUND="4">
            <ROW MODID="1" RECORDID="1">
                <COL><DATA>tank1</DATA></COL>
                <COL><DATA>1/1/2014</DATA></COL>
                <COL><DATA>data1</DATA></COL>
            </ROW>
            <ROW MODID="1" RECORDID="2">
                <COL><DATA>tank2</DATA></COL>
                <COL><DATA>1/1/2014</DATA></COL>
                <COL><DATA>data3</DATA></COL>
            </ROW>
            <ROW MODID="1" RECORDID="3">
                <COL><DATA>tank1</DATA></COL>
                <COL><DATA>1/2/2014</DATA></COL>
                <COL><DATA>data2</DATA></COL>
            </ROW>
            <ROW MODID="1" RECORDID="4">
                <COL><DATA>tank1</DATA></COL>
                <COL><DATA>1/1/2014</DATA></COL>
                <COL><DATA>data4</DATA></COL>
            </ROW>
        </RESULTSET>
    </FMPXMLRESULT>
    

    以下样式表:

    XSLT 1.0

    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:fmp="http://www.filemaker.com/fmpxmlresult"
    exclude-result-prefixes="fmp">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <xsl:key name="tanknumber" match="fmp:ROW" use="fmp:COL[1]"/>
    <xsl:key name="fishdate" match="fmp:ROW" use="concat(fmp:COL[1], '|', fmp:COL[2])"/>
    
    <xsl:template match="/">
        <fishroom>
            <!-- create a group for each distinct tank -->
            <xsl:for-each select="fmp:FMPXMLRESULT/fmp:RESULTSET/fmp:ROW[generate-id()=generate-id(key('tanknumber',fmp:COL[1]))]">
                <xsl:element name="{fmp:COL[1]/fmp:DATA}">
                   <!-- create a subgroup for each distinct date within a tank -->
                   <xsl:for-each select="key('tanknumber', fmp:COL[1])[generate-id()=generate-id(key('fishdate',concat(fmp:COL[1], '|', fmp:COL[2])))]"> 
                        <date>
                            <xsl:value-of select="fmp:COL[2]/fmp:DATA"/>
                            <!-- enumerate the values in the current subgroup -->
                             <xsl:for-each select="key('fishdate',concat(fmp:COL[1], '|', fmp:COL[2]))">
                                 <value>
                                    <xsl:value-of select="fmp:COL[3]/fmp:DATA"/>
                                </value>
                            </xsl:for-each>
                        </date>
                    </xsl:for-each>
                </xsl:element>
            </xsl:for-each>
        </fishroom>
    </xsl:template>
    
    </xsl:stylesheet>
    

    将返回此结果

    <?xml version="1.0" encoding="UTF-8"?>
    <fishroom>
       <tank1>
          <date>1/1/2014<value>data1</value>
             <value>data4</value>
          </date>
          <date>1/2/2014<value>data2</value>
          </date>
       </tank1>
       <tank2>
          <date>1/1/2014<value>data3</value>
          </date>
       </tank2>
    </fishroom>
    

    注意:
    我不知道您的目标应用程序的要求是什么。上面输出的XML格式有两个弱点,通常会试图避免:

    1. 兄弟元素名称的连续编号;
    2. 混合内容。