如何使用XSLT 1.0将Excel转换为带有嵌套元素的XML?

我想转换一个新的结构与嵌套元素从Excel导出的XML结构。 对于我来说,用XSLT v1.0来解决这个问题有点棘手。

我的目标是将行数据放入结果xml所需的层。 所以如果一行只包含1个数据的单元格,那么它就是一个例子:

<projects> <category name="001"> ... </category> </projects> 

如果一行有2个数据单元,则它代表一个区域,应该是previos类别的子节点。

 <projects> <category name="001"> <region name="AAA">...</region> <region name="BBB">...</region> </category> </projects> 

如果该行有3或4个数据单元,则表示一个帐户,该帐户应该是之前区域的子帐户。

 <projects> <category name="001"> <region name="AAA"> <account name="lorem">...</account> <account name="ipsum">...</account> </region> <region name="BBB">...</region> ... </category> </projects> 

好吧,我到目前为止:这是来​​自Excel的XML文件。 它具有重复行元素的简单结构。 每行包含5个单元格,但不是每个单元格也总是包含一个Data元素。 我试图用这个来确定每行代表什么样的信息。

  <Table ss:ExpandedColumnCount="6" ss:ExpandedRowCount="69" x:FullColumns="1" x:FullRows="1" ss:StyleID="s62" ss:DefaultColumnWidth="69"> <Row ss:AutoFitHeight="0" ss:Height="14.25"> <Cell ss:Index="2" ss:StyleID="s68"/> <Cell ss:StyleID="s69"/> <Cell ss:StyleID="s68"/> <Cell ss:StyleID="s68"/> <Cell ss:StyleID="s68"/> </Row> <Row ss:AutoFitHeight="0" ss:Height="15"> <Cell ss:Index="2" ss:StyleID="s70"><Data ss:Type="String">Categorie 004</Data></Cell> <Cell ss:StyleID="s71"/> <Cell ss:StyleID="s70"/> <Cell ss:StyleID="s72"/> <Cell ss:StyleID="s70"/> </Row> <Row ss:AutoFitHeight="0" ss:Height="14.25"> <Cell ss:Index="2" ss:StyleID="s68"><Data ss:Type="String">AAA</Data></Cell> <Cell ss:StyleID="s69"/> <Cell ss:StyleID="s69"><Data ss:Type="String">X</Data></Cell> <Cell ss:StyleID="s73"/> <Cell ss:StyleID="s74"><Data ss:Type="Number">0.01</Data></Cell> </Row> <Row ss:AutoFitHeight="0" ss:Height="14.25"> <Cell ss:Index="2" ss:StyleID="s68"/> <Cell ss:StyleID="s69"/> <Cell ss:StyleID="s68"/> <Cell ss:StyleID="s73"/> <Cell ss:StyleID="s68"/> </Row> <Row ss:Height="14.25"> <Cell ss:Index="2" ss:StyleID="s68"/> <Cell ss:StyleID="s69"/> <Cell ss:StyleID="s68"/> <Cell ss:StyleID="s73"/> <Cell ss:StyleID="s68"/> </Row> <Row ss:AutoFitHeight="0" ss:Height="14.25"> <Cell ss:Index="2" ss:StyleID="s68"/> <Cell ss:StyleID="s69"/> <Cell ss:StyleID="s68"/> <Cell ss:StyleID="s73"/> <Cell ss:StyleID="s68"/> </Row> <Row ss:AutoFitHeight="0" ss:Height="15"> <Cell ss:Index="2" ss:StyleID="s70"><Data ss:Type="String">Categorie 001</Data></Cell> <Cell ss:StyleID="s71"/> <Cell ss:StyleID="s70"/> <Cell ss:StyleID="s72"/> <Cell ss:StyleID="s70"/> </Row> <Row ss:AutoFitHeight="0" ss:Height="14.25"> <Cell ss:Index="2" ss:StyleID="s82"><Data ss:Type="String">AAA</Data></Cell> <Cell ss:StyleID="s83"/> <Cell ss:StyleID="s82"/> <Cell ss:StyleID="s84"/> <Cell ss:StyleID="s85"><Data ss:Type="Number">3.0800000000000001E-2</Data></Cell> </Row> <Row ss:AutoFitHeight="0" ss:Height="14.25"> <Cell ss:Index="2" ss:StyleID="s68"><Data ss:Type="String">dolor</Data></Cell> <Cell ss:StyleID="s69"><Data ss:Type="Number">123</Data></Cell> <Cell ss:StyleID="s69"><Data ss:Type="String">A</Data></Cell> <Cell ss:StyleID="s86"/> <Cell ss:StyleID="s74"><Data ss:Type="Number">0.01</Data></Cell> </Row> <Row ss:AutoFitHeight="0" ss:Height="15"> <Cell ss:Index="2" ss:StyleID="s68"><Data ss:Type="String">sit amet</Data></Cell> <Cell ss:StyleID="s69"><Data ss:Type="Number">445</Data></Cell> <Cell ss:StyleID="s69"><Data ss:Type="String">B</Data></Cell> <Cell ss:StyleID="s86"/> <Cell ss:StyleID="s74"><Data ss:Type="Number">0.03</Data></Cell> </Row> <Row ss:AutoFitHeight="0" ss:Height="14.25"> <Cell ss:Index="2" ss:StyleID="s68"><Data ss:Type="String">consetetur</Data></Cell> <Cell ss:StyleID="s69"><Data ss:Type="Number">36</Data></Cell> <Cell ss:StyleID="s69"><Data ss:Type="String">B</Data></Cell> <Cell ss:StyleID="s86"/> <Cell ss:StyleID="s74"><Data ss:Type="Number">8.0000000000000004E-4</Data></Cell> </Row> <Row ss:AutoFitHeight="0" ss:Height="14.25"> <Cell ss:Index="2" ss:StyleID="s82"><Data ss:Type="String">BBB</Data></Cell> <Cell ss:StyleID="s83"/> <Cell ss:StyleID="s82"/> <Cell ss:StyleID="s84"/> <Cell ss:StyleID="s85"><Data ss:Type="Number">0.03</Data></Cell> </Row> <Row ss:AutoFitHeight="0" ss:Height="14.25"> <Cell ss:Index="2" ss:StyleID="s68"><Data ss:Type="String">sadipscing</Data></Cell> <Cell ss:StyleID="s69"><Data ss:Type="Number">666</Data></Cell> <Cell ss:StyleID="s69"><Data ss:Type="String">A</Data></Cell> <Cell ss:StyleID="s86"/> <Cell ss:StyleID="s74"><Data ss:Type="Number">0.01</Data></Cell> </Row> <Row ss:AutoFitHeight="0" ss:Height="15"> <Cell ss:Index="2" ss:StyleID="s68"><Data ss:Type="String">elitr</Data></Cell> <Cell ss:StyleID="s69"><Data ss:Type="Number">97</Data></Cell> <Cell ss:StyleID="s69"><Data ss:Type="String">C</Data></Cell> <Cell ss:StyleID="s86"/> <Cell ss:StyleID="s74"><Data ss:Type="Number">0.02</Data></Cell> </Row> <Row ss:AutoFitHeight="0" ss:Height="15"> <Cell ss:Index="2" ss:StyleID="s68"/> <Cell ss:StyleID="s69"/> <Cell ss:StyleID="s68"/> <Cell ss:StyleID="s73"/> <Cell ss:StyleID="s68"/> </Row> <Row ss:AutoFitHeight="0" ss:Height="14.25"> <Cell ss:Index="2" ss:StyleID="s70"><Data ss:Type="String">Categorie 001</Data></Cell> <Cell ss:StyleID="s71"/> <Cell ss:StyleID="s70"/> <Cell ss:StyleID="s72"/> <Cell ss:StyleID="s70"/> </Row> <Row ss:AutoFitHeight="0" ss:Height="14.25"> <Cell ss:Index="2" ss:StyleID="s82"><Data ss:Type="String">AAA</Data></Cell> <Cell ss:StyleID="s83"/> <Cell ss:StyleID="s82"/> <Cell ss:StyleID="s84"/> <Cell ss:StyleID="s85"><Data ss:Type="Number">0.04</Data></Cell> </Row> <Row ss:AutoFitHeight="0" ss:Height="14.25"> <Cell ss:Index="2" ss:StyleID="s68"><Data ss:Type="String">aliquyam</Data></Cell> <Cell ss:StyleID="s69"><Data ss:Type="Number">65</Data></Cell> <Cell ss:StyleID="s69"><Data ss:Type="String">A</Data></Cell> <Cell ss:StyleID="s86"/> <Cell ss:StyleID="s74"><Data ss:Type="Number">0.02</Data></Cell> </Row> <Row ss:AutoFitHeight="0" ss:Height="14.25"> <Cell ss:Index="2" ss:StyleID="s68"><Data ss:Type="String">ipsum</Data></Cell> <Cell ss:StyleID="s69"><Data ss:Type="Number">99</Data></Cell> <Cell ss:StyleID="s69"><Data ss:Type="String">B</Data></Cell> <Cell ss:StyleID="s86"/> <Cell ss:StyleID="s74"><Data ss:Type="Number">0.02</Data></Cell> </Row> <Row ss:AutoFitHeight="0" ss:Height="14.25"> <Cell ss:Index="2" ss:StyleID="s82"><Data ss:Type="String">BBB</Data></Cell> <Cell ss:StyleID="s83"/> <Cell ss:StyleID="s82"/> <Cell ss:StyleID="s84"/> <Cell ss:StyleID="s85"><Data ss:Type="Number">0.01</Data></Cell> </Row> <Row ss:AutoFitHeight="0" ss:Height="14.25"> <Cell ss:Index="2" ss:StyleID="s68"><Data ss:Type="String">lorem</Data></Cell> <Cell ss:StyleID="s69"><Data ss:Type="Number">321</Data></Cell> <Cell ss:StyleID="s69"><Data ss:Type="String">C</Data></Cell> <Cell ss:StyleID="s86"/> <Cell ss:StyleID="s74"><Data ss:Type="Number">0.01</Data></Cell> </Row> </Table> 

到目前为止,我已经创build了以下样式表,并能够根据需要过滤所有信息。

 <!-- Filter Excel Cells --> <xsl:template match="ss:Row"> <xsl:if test="count(.//ss:Data) &gt; 0"> <xsl:choose> <xsl:when test="count(.//ss:Data)=1"> <Categorie> <xsl:value-of select=".//ss:Cell[1]/ss:Data"/> </Categorie> </xsl:when> <xsl:when test="count(.//ss:Data)=2"> <Region> <xsl:value-of select=".//ss:Cell[1]/ss:Data"/> </Region> </xsl:when> <xsl:when test="count(.//ss:Data)=3"> <xsl:choose> <xsl:when test=".//ss:Cell[5]/ss:Data='Rating'"> <Header> <Text1> <xsl:value-of select=".//ss:Cell[1]/ss:Data"/> </Text1> <Text2> <xsl:value-of select=".//ss:Cell[3]/ss:Data"/> </Text2> <Text3> <xsl:value-of select=".//ss:Cell[5]/ss:Data"/> </Text3> </Header> </xsl:when> <xsl:otherwise> <Account> <Name> <xsl:value-of select=".//ss:Cell[1]/ss:Data"/> </Name> <Value> <xsl:value-of select=".//ss:Cell[3]/ss:Data"/> </Value> <Rating> <xsl:value-of select=".//ss:Cell[5]/ss:Data"/> </Rating> </Account> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="count(.//ss:Data)=4"> <xsl:choose> <xsl:when test=".//ss:Cell[5]/ss:Data='Gewicht'"> <Header> <Text1> <xsl:value-of select=".//ss:Cell[1]/ss:Data"/> </Text1> <Text2> <xsl:value-of select=".//ss:Cell[2]/ss:Data"/> </Text2> <Text3> <xsl:value-of select=".//ss:Cell[3]/ss:Data"/> </Text3> <Text4> <xsl:value-of select=".//ss:Cell[5]/ss:Data"/> </Text4> </Header> </xsl:when> <xsl:otherwise> <Account> <Name> <xsl:value-of select=".//ss:Cell[1]/ss:Data"/> </Name> <Type> <xsl:value-of select=".//ss:Cell[2]/ss:Data"/> </Type> <Value> <xsl:value-of select=".//ss:Cell[3]/ss:Data"/> </Value> <Rating> <xsl:value-of select=".//ss:Cell[5]/ss:Data"/> </Rating> </Account> </xsl:otherwise> </xsl:choose> </xsl:when> </xsl:choose> </xsl:if> </xsl:template> 

我的结果现在看起来如此:

 <?xml version="1.0" encoding="UTF-8"?> <Projects xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> <Categorie>Categorie 004</Categorie> <Region>AAA</Region> <Account> <Name>AAA</Name> <Value>X</Value> <Rating>0.01</Rating> </Account> <Account> <Name>Name</Name> <Type>Value</Type> <Value>Type</Value> <Rating>Rating</Rating> </Account> <Categorie>Categorie 001</Categorie> <Region>AAA</Region> <Account> <Name>dolor</Name> <Type>123</Type> <Value>A</Value> <Rating>0.01</Rating> </Account> <Account> <Name>sit amet</Name> <Type>445</Type> <Value>B</Value> <Rating>0.03</Rating> </Account> <Account> <Name>consetetur</Name> <Type>36</Type> <Value>B</Value> <Rating>8.0000000000000004E-4</Rating> </Account> <Region>BBB</Region> <Account> <Name>sadipscing</Name> <Type>666</Type> <Value>A</Value> <Rating>0.01</Rating> </Account> <Account> <Name>elitr</Name> <Type>97</Type> <Value>C</Value> <Rating>0.02</Rating> </Account> <Account> <Name>Name</Name> <Type>Value</Type> <Value>Type</Value> <Rating>Rating</Rating> </Account> <Categorie>Categorie 001</Categorie> <Region>AAA</Region> <Account> <Name>aliquyam</Name> <Type>65</Type> <Value>A</Value> <Rating>0.02</Rating> </Account> <Account> <Name>ipsum</Name> <Type>99</Type> <Value>B</Value> <Rating>0.02</Rating> </Account> <Region>BBB</Region> <Account> <Name>lorem</Name> <Type>321</Type> <Value>C</Value> <Rating>0.01</Rating> </Account> </Projects> 

不错(对我来说),但我需要的数据嵌套像这样,而不是每个数据在同一级别。 我需要你的帮助!

 <?xml version="1.0" encoding="UTF-8"?> <Projects xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> <Categorie name="001"/> <Region name="AAA"> <Account> <Name>Name</Name> <Type>Value</Type> <Value>Type</Value> <Rating>Rating</Rating> </Account> <Account> <Name>Name</Name> <Type>Value</Type> <Value>Type</Value> <Rating>Rating</Rating> </Account> </Region> <Region name="BBB"> <Account> <Name>Name</Name> <Type>Value</Type> <Value>Type</Value> <Rating>Rating</Rating> </Account> <Account> <Name>Name</Name> <Type>Value</Type> <Value>Type</Value> <Rating>Rating</Rating> </Account> ... </Region> <Categorie name="002"/> <Region name="AAA"> ... </Region> </Categorie> </Projects> 

我相信你需要在一些标签上使用元素/属性调用来把它们放在你需要的格式,比如下面的

 <xsl:element name="Categorie"> <xsl:attribute name="name"> <xsl:value-of select=".//ss:Cell[1]/ss:Data"/> </xsl:attribute> <xsl:element name="Region"> <xsl:attribute name="name"> <xsl:value-of select=".//ss:Cell[1]/ss:Data"/> </xsl:attribute> //rest of transform here </xsl:element> </xsl:element> 

我还没有进行任何testing,但这应该指出你需要的方向