如何将XSLT从Rows转换为Elements

时间:2014-09-10 07:02:10

标签: xml xslt

我正在寻求有关corrext XSLT方法的建议,以便将行的XML输出转换为正确的逻辑元素。

作为一个例子,我有以下输出

<?xml version="1.0" encoding="utf-8"?>
<Report>
    <Field>GetMembershipDetails</Field>
    <Row>
        <Item>MembershipID</Item>
        <Item>MemberNumber</Item>
        <Item>MembershipStatus</Item>
        <Item>BenefitStartDate</Item>
        <Item>BenefitEndDate</Item>
        <Item>MembershipStartDate</Item>
        <Item>MembershipEndDate</Item>
        <Item>MembershpResignationDate</Item>
        <Item>MembershipAnniversaryDate</Item>
        <Item>MembershipType</Item>
        <Item>ContactId</Item>
        <Item>ContactTitle</Item>
        <Item>ContactFirstName</Item>
        <Item>ContactLastName</Item>
        <Item>ContactGender</Item>
        <Item>ContactDateOfBirth</Item>
        <Item>ContactEmployeeNumber</Item>
        <Item>ContactEmployeDateJoined</Item>
        <Item>ContactCorporateAccountNo</Item>
        <Item>ContactEmailAddress</Item>
        <Item>ContactPostalStreet</Item>
        <Item>ContactPostalCity</Item>
        <Item>ContactPostalState</Item>
        <Item>ContactPostalPostCode</Item>
        <Item>ContactResidentialStreet</Item>
        <Item>ContactResidentialState</Item>
        <Item>ContactResidentialCity</Item>
        <Item>ContactResidentialPostCode</Item>
        <Item>ContactResidentialCountry</Item>
        <Item>ContactType</Item>
        <Item>ProductName</Item>
        <Item>ProductDescription</Item>
        <Item>ProductType</Item>
        <Item>ProductAmount</Item>
        <Item>MembershipProductID</Item>
    </Row>
    <Row>
        <Item>8</Item>
        <Item>A2000</Item>
        <Item>Current</Item>
        <Item>No Value</Item>
        <Item>No Value</Item>
        <Item>No Value</Item>
        <Item>No Value</Item>
        <Item>No Value</Item>
        <Item>No Value</Item>
        <Item>Current</Item>
        <Item>109</Item>
        <Item>Mr</Item>
        <Item>John</Item>
        <Item>Foley</Item>
        <Item>Male</Item>
        <Item>10/09/2014</Item>
        <Item>No Value</Item>
        <Item>No Value</Item>
        <Item>0</Item>
        <Item>jfoley@test.com</Item>
        <Item>No Value</Item>
        <Item>No Value</Item>
        <Item>No Value</Item>
        <Item>0</Item>
        <Item>No Value</Item>
        <Item>No Value</Item>
        <Item>No Value</Item>
        <Item>No Value</Item>
        <Item>Australia</Item>
        <Item>Primary</Item>
        <Item>No Value</Item>
        <Item>No Value</Item>
        <Item>No Value</Item>
        <Item>0</Item>
        <Item>8</Item>
    </Row>
</Report>

哪个应该像

<Table>
<Row>
<MembershipID>8</MembershipID>
...
...
</Row>
</Table>

甚至

<Table>
<Row>
<Column name="MembershipID">8</Column>
...
</Row>
</Table>

提前致谢

2 个答案:

答案 0 :(得分:1)

第二种选择绝对是可取的。试试这种方式:

XSLT 1.0

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

<xsl:key name="column-name" match="Row[1]/Item" use="count(preceding-sibling::Item)" />

<xsl:template match="/">
    <Table>
        <xsl:for-each select="Report/Row[position() > 1]">
            <Row>
                <xsl:apply-templates select="Item"/>
            </Row>
        </xsl:for-each>
    </Table>
</xsl:template>

<xsl:template match="Item">
    <Column name="{key('column-name', count(preceding-sibling::Item))}">
        <xsl:value-of select="."/>
    </Column>
</xsl:template>

</xsl:stylesheet>

-

或许你更喜欢改变:

<xsl:template match="Item">

为:

<xsl:template match="Item[not(.='No Value')]">

答案 1 :(得分:1)

上面的答案对于第二种选择是正确的。

如果你决定做第一个选项,这就是结果。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" omit-xml-declaration="yes" method="xml"/>
    <!-- Select the heading names into a variable -->
    <xsl:variable name="headingNames" select="//Row[1]/Item"/>
    <xsl:template match="/">
        <xsl:for-each select="Report/Row">
            <!--Check to make sure that we only select the second row onwards (as first row is the headings)--> 
            <xsl:if test="position() &gt; 1">
            <Row>
                <xsl:variable name="rowVal" select="."/>
                <xsl:for-each select="$rowVal/Item">
                    <xsl:variable name="currentPos" select="position()"/>
                    <xsl:element name="{$headingNames[$currentPos]}">
                        <xsl:value-of select="."/>
                    </xsl:element>
                </xsl:for-each>
                </Row>
            </xsl:if>           
        </xsl:for-each>     
    </xsl:template>
</xsl:stylesheet>