XSLT处理从Excel转换的XML

时间:2019-06-30 22:30:38

标签: excel xml xslt

这是从Excel Mac(Excel 2004 XML格式)转换的XML文件:

Excel文件具有四个字段(字段1至4),每个字段具有数据(字段n_Datam,n,m范围为1至4)

XML输出如下:

<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
        xmlns:o="urn:schemas-microsoft-com:office:office"
        xmlns:x="urn:schemas-microsoft-com:office:excel"
        xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
        xmlns:html="http://www.w3.org/TR/REC-html40">
    <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
        <Author>Passiflora Cui</Author>
        <LastAuthor>Passiflora Cui</LastAuthor>
        <Created>2019-06-30T21:49:41Z</Created>
        <LastSaved>2019-06-30T21:50:54Z</LastSaved>
        <Version>16.00</Version>
    </DocumentProperties>
    <OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
        <AllowPNG/>
    </OfficeDocumentSettings>
    <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
        <WindowHeight>16940</WindowHeight>
        <WindowWidth>27640</WindowWidth>
        <WindowTopX>5580</WindowTopX>
        <WindowTopY>3560</WindowTopY>
        <ProtectStructure>False</ProtectStructure>
        <ProtectWindows>False</ProtectWindows>
    </ExcelWorkbook>
    <Styles>
        <Style ss:ID="Default" ss:Name="Normal">
            <Alignment ss:Vertical="Bottom"/>
            <Borders/>
            <Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#000000"/>
            <Interior/>
            <NumberFormat/>
            <Protection/>
        </Style>
        <Style ss:ID="s62">
            <Alignment ss:Horizontal="Center" ss:Vertical="Bottom"/>
        </Style>
    </Styles>
    <Worksheet ss:Name="Sheet1">
        <Table ss:ExpandedColumnCount="4" ss:ExpandedRowCount="5" x:FullColumns="1"
                x:FullRows="1" ss:DefaultColumnWidth="65" ss:DefaultRowHeight="16">
            <Column ss:AutoFitWidth="0" ss:Width="74"/>
            <Row>
                <Cell>
                    <Data ss:Type="String">Field1</Data>
                </Cell>
                <Cell>
                    <Data ss:Type="String">Field2</Data>
                </Cell>
                <Cell>
                    <Data ss:Type="String">Field3</Data>
                </Cell>
                <Cell>
                    <Data ss:Type="String">Field4</Data>
                </Cell>
            </Row>
            <Row>
                <Cell>
                    <Data ss:Type="String">Field1_Data1</Data>
                </Cell>
                <Cell ss:StyleID="s62">
                    <Data ss:Type="String">Field2_Data1</Data>
                </Cell>
                <Cell>
                    <Data ss:Type="String">Field3_Data1</Data>
                </Cell>
                <Cell>
                    <Data ss:Type="String">Field4_Data1</Data>
                </Cell>
            </Row>
            <Row>
                <Cell>
                    <Data ss:Type="String">Field1_Data2</Data>
                </Cell>
                <Cell ss:StyleID="s62">
                    <Data ss:Type="String">Field2_Data2</Data>
                </Cell>
                <Cell>
                    <Data ss:Type="String">Field3_Data2</Data>
                </Cell>
                <Cell>
                    <Data ss:Type="String">Field4_Data2</Data>
                </Cell>
            </Row>
            <Row>
                <Cell>
                    <Data ss:Type="String">Field1_Data3</Data>
                </Cell>
                <Cell ss:StyleID="s62">
                    <Data ss:Type="String">Field2_Data3</Data>
                </Cell>
                <Cell>
                    <Data ss:Type="String">Field3_Data3</Data>
                </Cell>
                <Cell>
                    <Data ss:Type="String">Field4_Data3</Data>
                </Cell>
            </Row>
            <Row>
                <Cell>
                    <Data ss:Type="String">Field1_Data4</Data>
                </Cell>
                <Cell ss:StyleID="s62">
                    <Data ss:Type="String">Field2_Data4</Data>
                </Cell>
                <Cell>
                    <Data ss:Type="String">Field3_Data4</Data>
                </Cell>
                <Cell>
                    <Data ss:Type="String">Field4_Data4</Data>
                </Cell>
            </Row>
        </Table>
        <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
            <PageSetup>
                <Header x:Margin="0.3"/>
                <Footer x:Margin="0.3"/>
                <PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
            </PageSetup>
            <Selected/>
            <Panes>
                <Pane>
                    <Number>3</Number>
                    <ActiveRow>5</ActiveRow>
                    <ActiveCol>5</ActiveCol>
                </Pane>
            </Panes>
            <ProtectObjects>False</ProtectObjects>
            <ProtectScenarios>False</ProtectScenarios>
        </WorksheetOptions>
    </Worksheet>
</Workbook>

我的XSLT文件是这样的:

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

    <xsl:template match = "Table">
        <Result>
            <xsl:for-each select="Row[position() > 1]">
                <Test>
                    <Field1><xsl:value-of select = "Cell[1]/Data"/></Field1>
                    <Field2><xsl:value-of select = "Cell[2]/Data"/></Field2>
                    <Field3><xsl:value-of select = "Cell[3]/Data"/></Field3>
                    <Field4><xsl:value-of select = "Cell[4]/Data"/></Field4>
                </Test>
            </xsl:for-each>
        </Result>
    </xsl:template>
</xsl:stylesheet>

所需的结果文件如下所示:

<Result>
    <Test>
        <Field1>Field1_Data1</Field1>
        <Field2>Field2_Data1</Field2>
        <Field3>Field3_Data1</Field3>
        <Field4>Field4_Data1</Field4>
    </Test>
    <Test>
        <Field1>Field1_Data2</Field1>
        <Field2>Field2_Data2</Field2>
        <Field3>Field3_Data2</Field3>
        <Field4>Field4_Data2</Field4>
    </Test>
    <Test>
        <Field1>Field1_Data3</Field1>
        <Field2>Field2_Data3</Field2>
        <Field3>Field3_Data3</Field3>
        <Field4>Field4_Data3</Field4>
    </Test>
    <Test>
        <Field1>Field1_Data4</Field1>
        <Field2>Field2_Data4</Field2>
        <Field3>Field3_Data4</Field3>
        <Field4>Field4_Data4</Field4>
    </Test>
</Result>

但是,我的XSLT无法正常工作,并且它输出所有字符串,就好像尚未执行<xsl:template>一样。我已经尝试了很多XPath,例如//TableWorkbook/Worksheet/Table,但是它们都不起作用!谁能告诉我我错了吗?预先感谢!

1 个答案:

答案 0 :(得分:2)

您的解决方案失败了,因为您没有考虑名称空间。您的XML根元素<Workbook>设置了默认名称空间xmlns="urn:schemas-microsoft-com:office:spreadsheet",因此它本身及其所有子元素都具有相同的名称空间。因此,您还必须在XSLT中设置此名称空间。

在这里,我使用前缀wb来指定名称空间

xmlns:wb="urn:schemas-microsoft-com:office:spreadsheet"

因此,您想要的XSLT-1.0文件可能看起来像

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version = "1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:wb="urn:schemas-microsoft-com:office:spreadsheet">
    <xsl:output method = "xml" indent = "yes"/>

    <!-- Ignore all free text() nodes -->
    <xsl:template match="text()" />

    <xsl:template match = "/wb:Workbook/wb:Worksheet/wb:Table">
        <xsl:element name="Result">
            <xsl:for-each select="wb:Row[position() > 1]">
                <Test>
                    <Field1><xsl:value-of select = "wb:Cell[1]/wb:Data"/></Field1>
                    <Field2><xsl:value-of select = "wb:Cell[2]/wb:Data"/></Field2>
                    <Field3><xsl:value-of select = "wb:Cell[3]/wb:Data"/></Field3>
                    <Field4><xsl:value-of select = "wb:Cell[4]/wb:Data"/></Field4>
                </Test>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

结果如预期。
新定义的名称空间的前缀wb:已添加到所有XPath元素引用中。这就是使代码正常工作所要做的一切。