XSLT如何将XML转换为新的元素组和属性

时间:2012-02-29 21:03:31

标签: xslt xslt-1.0 xslt-2.0

我一直在努力想弄清楚如何使用XSLT转换XML。主要目标是获取XML源数据,并根据月份数据重复/创建新行。例如,当前每行具有“X”量的月份数据全部作为一行。我试图打破这一点,以便每行只包含一个月的数据。然后下一行将包含相同的标题信息,但包含原始源行的下一个月数据。希望这是有道理的。我还试图弄清楚如何在一行中配置月份列,以触发该月份数值的新值作为目标XML中的新值,如我的示例所示。任何建议都会非常感激。

源代码:

<?xml version="1.0"?>
<?xml-stylesheet type="txt/xsl" href="transform.xsl"?>
<Report>
<ReportData>
<DataSet>
<Row rowNum="1">
<Column name="Title 1"><Val xsi:type="xsd:string">Sample 1</Val></Column>
<Column name="Title 2"><Val xsi:type="xsd:string">Sample 2</Val></Column>
<Column name="Title 3"><Val xsi:type="xsd:string">Sample 3</Val></Column>
<Column name="Title 4"><Val xsi:type="xsd:string">Sample 4</Val></Column>
<Column name="Title 5"><Val xsi:type="xsd:string">160X600</Val></Column>
<Column name="Title 6"><Val xsi:type="xsd:string" xsi:nil="true"></Val></Column>
<Column name="Title 7"><Val xsi:type="xsd:integer">1325600</Val></Column>
<Column name="MAR_Month_Total"><Val xsi:type="xsd:float">19.00</Val></Column>
<Column name="MAR_Month_Total_B"><Val xsi:type="xsd:float">22.00</Val></Column>
<Column name="APR_Month_Total"><Val xsi:type="xsd:float">18.00</Val></Column>
<Column name="APR_Month_Total_B"><Val xsi:type="xsd:float">35.00</Val></Column>
<Column name="MAY_Month_Total"><Val xsi:type="xsd:float">25.00</Val></Column>
<Column name="MAY_Month_Total_B"><Val xsi:type="xsd:float">15.00</Val></Column>
</Row>
<RowNum="2">
<Column name="Title 1"><Val xsi:type="xsd:string">Sample 5</Val></Column>
<Column name="Title 2"><Val xsi:type="xsd:string">Sample 6</Val></Column>
<Column name="Title 3"><Val xsi:type="xsd:string">Sample 7</Val></Column>
<Column name="Title 4"><Val xsi:type="xsd:string">Sample 8</Val></Column>
<Column name="Title 5"><Val xsi:type="xsd:string">250X600</Val></Column>
<Column name="Title 6"><Val xsi:type="xsd:string" xsi:nil="true"></Val></Column>
<Column name="Title 7"><Val xsi:type="xsd:integer">5600</Val></Column>
<Column name="MAR_Month_Total"><Val xsi:type="xsd:float">0.00</Val></Column>
<Column name="MAR_Month_Total_B"><Val xsi:type="xsd:float">5.00</Val></Column>
<Column name="APR_Month_Total"><Val xsi:type="xsd:float">24.00</Val></Column>
<Column name="APR_Month_Total_B"><Val xsi:type="xsd:float">10.00</Val></Column>
<Column name="MAY_Month_Total"><Val xsi:type="xsd:float">36.00</Val></Column>
<Column name="MAY_Month_Total_B"><Val xsi:type="xsd:float">15.00</Val></Column></Row>
</DataSet>
</ReportData>
</Report>

结果XML示例

<?xml version="1.0"?>
<?xml-stylesheet type="txt/xsl" href="transform.xsl"?>
<Report>
<ReportData>
<DataSet>
<Row rowNum="1">
<Column name="Title 1"><Val xsi:type="xsd:string">Sample 1</Val></Column>
<Column name="Title 2"><Val xsi:type="xsd:string">Sample 2</Val></Column>
<Column name="Title 3"><Val xsi:type="xsd:string">Sample 3</Val></Column>
<Column name="Title 4"><Val xsi:type="xsd:string">Sample 4</Val></Column>
<Column name="Title 5"><Val xsi:type="xsd:string">160X600</Val></Column>
<Column name="Title 6"><Val xsi:type="xsd:string" xsi:nil="true"></Val></Column>
<Column name="Title 7"><Val xsi:type="xsd:integer">1325600</Val></Column>
<Column name="MAR_Month_ID"><Val xsi:type="xsd:integer">3</Val></Column>
<Column name="YEAR"><Val xsi:type="xsd:integer">2012</Val></Column>
<Column name="MAR_Month_Total"><Val xsi:type="xsd:float">19.00</Val></Column>
<Column name="MAR_Month_Total_B"><Val xsi:type="xsd:float">22.00</Val></Column>
</Row>
<Row rowNum="2">
<Column name="Title 1"><Val xsi:type="xsd:string">Sample 1</Val></Column>
<Column name="Title 2"><Val xsi:type="xsd:string">Sample 2</Val></Column>
<Column name="Title 3"><Val xsi:type="xsd:string">Sample 3</Val></Column>
<Column name="Title 4"><Val xsi:type="xsd:string">Sample 4</Val></Column>
<Column name="Title 5"><Val xsi:type="xsd:string">160X600</Val></Column>
<Column name="Title 6"><Val xsi:type="xsd:string" xsi:nil="true"></Val></Column>
<Column name="Title 7"><Val xsi:type="xsd:integer">1325600</Val></Column>
<Column name="APR_Month_ID"><Val xsi:type="xsd:integer">4</Val></Column>
<Column name="YEAR"><Val xsi:type="xsd:integer">2012</Val></Column>
<Column name="APR_Month_Total"><Val xsi:type="xsd:float">18.00</Val></Column>
<Column name="APR_Month_Total_B"><Val xsi:type="xsd:float">35.00</Val></Column>
</Row>
<Row rowNum="3">
<Column name="Title 1"><Val xsi:type="xsd:string">Sample 1</Val></Column>
<Column name="Title 2"><Val xsi:type="xsd:string">Sample 2</Val></Column>
<Column name="Title 3"><Val xsi:type="xsd:string">Sample 3</Val></Column>
<Column name="Title 4"><Val xsi:type="xsd:string">Sample 4</Val></Column>
<Column name="Title 5"><Val xsi:type="xsd:string">160X600</Val></Column>
<Column name="Title 6"><Val xsi:type="xsd:string" xsi:nil="true"></Val></Column>
<Column name="Title 7"><Val xsi:type="xsd:integer">1325600</Val></Column>
<Column name="MAY_Month_ID"><Val xsi:type="xsd:integer">5</Val></Column>
<Column name="YEAR"><Val xsi:type="xsd:integer">2012</Val></Column>
<Column name="MAY_Month_Total"><Val xsi:type="xsd:float">25.00</Val></Column>
<Column name="MAY_Month_Total_B"><Val xsi:type="xsd:float">15.00</Val></Column>
</Row>
<Row RowNum="4">
<Column name="Title 1"><Val xsi:type="xsd:string">Sample 5</Val></Column>
<Column name="Title 2"><Val xsi:type="xsd:string">Sample 6</Val></Column>
<Column name="Title 3"><Val xsi:type="xsd:string">Sample 7</Val></Column>
<Column name="Title 4"><Val xsi:type="xsd:string">Sample 8</Val></Column>
<Column name="Title 5"><Val xsi:type="xsd:string">250X600</Val></Column>
<Column name="Title 6"><Val xsi:type="xsd:string" xsi:nil="true"></Val></Column>
<Column name="Title 7"><Val xsi:type="xsd:integer">5600</Val></Column>
<Column name="MAR_Month_ID"><Val xsi:type="xsd:integer">3</Val></Column>
<Column name="YEAR"><Val xsi:type="xsd:integer">2012</Val></Column>
<Column name="MAR_Month_Total"><Val xsi:type="xsd:float">0.00</Val></Column>
<Column name="MAR_Month_Total_B"><Val xsi:type="xsd:float">5.00</Val></Column>
</Row>
<Row RowNum="5">
<Column name="Title 1"><Val xsi:type="xsd:string">Sample 5</Val></Column>
<Column name="Title 2"><Val xsi:type="xsd:string">Sample 6</Val></Column>
<Column name="Title 3"><Val xsi:type="xsd:string">Sample 7</Val></Column>
<Column name="Title 4"><Val xsi:type="xsd:string">Sample 8</Val></Column>
<Column name="Title 5"><Val xsi:type="xsd:string">250X600</Val></Column>
<Column name="Title 6"><Val xsi:type="xsd:string" xsi:nil="true"></Val></Column>
<Column name="Title 7"><Val xsi:type="xsd:integer">5600</Val></Column>
<Column name="APR_Month_ID"><Val xsi:type="xsd:integer">4</Val></Column>
<Column name="YEAR"><Val xsi:type="xsd:integer">2012</Val></Column>
<Column name="APR_Month_Total"><Val xsi:type="xsd:float">18.00</Val></Column>
<Column name="APR_Month_Total_B"><Val xsi:type="xsd:float">35.00</Val></Column>
</Row>
<Row rowNum"6">
<Column name="Title 1"><Val xsi:type="xsd:string">Sample 5</Val></Column>
<Column name="Title 2"><Val xsi:type="xsd:string">Sample 6</Val></Column>
<Column name="Title 3"><Val xsi:type="xsd:string">Sample 7</Val></Column>
<Column name="Title 4"><Val xsi:type="xsd:string">Sample 8</Val></Column>
<Column name="Title 5"><Val xsi:type="xsd:string">250X600</Val></Column>
<Column name="Title 6"><Val xsi:type="xsd:string" xsi:nil="true"></Val></Column>
<Column name="Title 7"><Val xsi:type="xsd:integer">5600</Val></Column>
<Column name="MAY_Month_ID"><Val xsi:type="xsd:integer">5</Val></Column>
<Column name="YEAR"><Val xsi:type="xsd:integer">2012</Val></Column>
<Column name="MAY_Month_Total"><Val xsi:type="xsd:float">18.00</Val></Column>
<Column name="MAY_Month_Total_B"><Val xsi:type="xsd:float">35.00</Val></Column>
</ROW>
</DataSet>
</ReportData>
</Report>

感谢任何帮助。 感谢

1 个答案:

答案 0 :(得分:0)

试试这个:

<!--- you need to complete this variable with all month keys: -->
<xsl:variable name="monthCodes" select="('JAN','FEB','MAR','APR','MAY','...')"/>
<xsl:template match="Row">
    <!-- saves the month-total columns in a variable-->
    <xsl:variable name="months" select="Column[contains(@name,'Month_Total')]"/>
    <!-- groups the $months: starts a new group, if the @name is matching on the regex 'Month_Total$' -->
    <xsl:for-each-group select="$months" group-starting-with="*[matches(@name,'Month_Total$')]">
        <Row>
            <xsl:variable name="rowNum" select="count(../preceding-sibling::Row/Column[matches(@name,'Month_Total$')]) + position()"/>
            <xsl:attribute name="rowNum" select="$rowNum"/>
            <!-- copies all Columns of the current <Row> witch are not in $months -->
            <xsl:copy-of select="../Column[not(contains(@name,'Month_Total'))]"/>
            <xsl:variable name="monthCode" select="substring(@name,1,3)"/>
            <Column name="{$monthCode}_Month_ID">
                <Val xsi:type="xsd:integer">
                    <xsl:value-of select="index-of($monthCodes,$monthCode)"/>
                </Val>
            </Column>
            <Column name="YEAR">
                <Val xsi:type="xsd:integer"><xsl:value-of select="year-from-date(current-date())"/></Val>
            </Column>
            <!-- copies all nodes of the current Row (the mont  h-total columns of the current month) -->
            <xsl:copy-of select="current-group()"/>
        </Row>
    </xsl:for-each-group>
</xsl:template>
<xsl:template match="node() | @*">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="node()"/>
    </xsl:copy>
</xsl:template>