xml转换 - 组合节点

时间:2014-04-16 22:23:53

标签: xml xslt

我有一个测试用例的数据集

<?xml version="1.0" encoding="UTF-8"?>
<STUDENTS_LIST dateGenerated="2014-01-01">
    <STUDENTS>
        <MALE>
            <STUDENT_ID>10000</STUDENT_ID>
            <F_NAME>REGGIE</F_NAME>
            <M_NAME/>
            <L_NAME>MILLER</L_NAME>
            <DOB>
                <YEAR>1980</YEAR>
            </DOB>
            <STUDENT_TYPE>MORNING</STUDENT_TYPE>
            <STUDENT_REF>BLUE</STUDENT_REF>
            <JOIN_DATE>04-20-2000</JOIN_DATE>
            <NOTES/>
            <FATHER_NAME>
                <NAME>MILLER A</NAME>
            </FATHER_NAME>
            <MOTHER_NAME>
                <NAME>MILLER B</NAME>
            </MOTHER_NAME>
            <REFRESH_DATE>04-14-2014</REFRESH_DATE>
            <CORE_SUBJECTS>
                <SUBJECT_A>CALCULUS A</SUBJECT_A>
                <SUBJECT_B>CALCULUS B</SUBJECT_B>
                <SUBJECT_C>PERFORMING ARTS</SUBJECT_C>
            </CORE_SUBJECTS>
            <OPT_SUBJECTS>
                <SUBJECT_A>AMERICAN HISTORY</SUBJECT_A>
                <SUBJECT_B/>
                <SUBJECT_C/>
            </OPT_SUBJECTS>
            <STUDENT_KEY>ABC10000-1</STUDENT_KEY>
            <STUDENT_KEY_CREATION_DATE>04-20-2000</STUDENT_KEY_CREATION_DATE>
        </MALE>
        <FEMALE>
            <STUDENT_ID>10001</STUDENT_ID>
            <F_NAME>REGINA</F_NAME>
            <M_NAME/>
            <L_NAME>MOON</L_NAME>
            <DOB>
                <YEAR>1980</YEAR>
            </DOB>
            <STUDENT_TYPE>MORNING</STUDENT_TYPE>
            <STUDENT_REF>BLUE</STUDENT_REF>
            <JOIN_DATE>04-20-2000</JOIN_DATE>
            <NOTES/>
            <FATHER_NAME>
                <NAME>MOON A</NAME>
            </FATHER_NAME>
            <MOTHER_NAME>
                <NAME>MOON B</NAME>
            </MOTHER_NAME>
            <REFRESH_DATE>04-14-2014</REFRESH_DATE>
            <CORE_SUBJECTS>
                <SUBJECT_A>CALCULUS A</SUBJECT_A>
                <SUBJECT_B>CALCULUS B</SUBJECT_B>
                <SUBJECT_C>PERFORMING ARTS</SUBJECT_C>
            </CORE_SUBJECTS>
            <OPT_SUBJECTS>
                <SUBJECT_A>AMERICAN HISTORY</SUBJECT_A>
                <SUBJECT_B/>
                <SUBJECT_C/>
            </OPT_SUBJECTS>
            <STUDENT_KEY>ABC10000-1</STUDENT_KEY>
            <STUDENT_KEY_CREATION_DATE>04-20-2000</STUDENT_KEY_CREATION_DATE>
        </FEMALE>
    </STUDENTS>
</STUDENTS_LIST>

需要使用xslt

转换为以下xml
<?xml version="1.0" encoding="UTF-8"?>
<classified date="2014-01-01">
    <students>
        <student>
            <student_id>10000</student_id>
            <fname>REGGIE</fname>
            <mname/>
            <lname>MILLER</lname>
            <sex>male</sex>
            <data>student_type: MORNING, student_ref: BLUE, father_name: MILLER A,
                mother_name: MILLER B, core_subjects : CALCULUS A, CALCULUS B, PERFORMING ARTS,
                opt_subjects: AMERICAN HISTORY, student_key: ABC10000-1, student_key_creation_date:
                04-20-2000, rec_refresh_date: 04-14-2014 </data>
            <dob>
                <year>1980</year>
            </dob>
            <joindate>04-20-2000</joindate>
        </student>
        <student>
            <student_id>10001</student_id>
            <fname>REGINA</fname>
            <mname/>
            <lname>MOON</lname>
            <sex>female</sex>
            <notes>student_type: MORNING, student_ref: BLUE, father_name: MOON A,
                mother_name: MOON B, core_subjects : CALCULUS A, CALCULUS B, PERFORMING ARTS,
                opt_subjects: AMERICAN HISTORY, student_key: ABC10000-1, student_key_creation_date:
                04-20-2000, rec_refresh_date: 04-14-2014 </notes>
            <dob>
                <year>1980</year>
            </dob>
            <joindate>04-20-2000</joindate>
        </student>
    </students>
</classified>

我使用@Joel M. Lamsen提供的以下XSLT来回答我的其他问题。

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

    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="STUDENT_TYPE|STUDENT_REF|FATHER_NAME|MOTHER_NAME|STUDENT_KEY|STUDENT_KEY_CREATION_DATE">
<xsl:value-of select="concat(name(), ': ', .)"/><xsl:text>&#xA;</xsl:text>
    </xsl:template>

    <xsl:template match="NOTES"/>

    <xsl:template match="REFRESH_DATE">
        <xsl:value-of select="concat('REC_REFRESH_DATE', ': ', .)"/><xsl:text>&#xA;</xsl:text>
    </xsl:template>

    <xsl:template match="CORE_SUBJECTS|OPT_SUBJECTS">
        <xsl:value-of select="concat(name(), ': ')"/>
        <xsl:for-each select="*[.!='']">
            <xsl:choose>
                <xsl:when test="position() != last()">
                    <xsl:value-of select="."/>
                    <xsl:text>, </xsl:text>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="."/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
        <xsl:text>&#xA;</xsl:text>
    </xsl:template>

    <xsl:template match="STUDENT">
        <xsl:copy>
            <xsl:apply-templates select="STUDENT_ID|F_NAME|M_NAME|L_NAME|NOTES|DOB"/>
            <NOTES>
                <xsl:text>&#xA;</xsl:text>
                <xsl:apply-templates select="STUDENT_TYPE"/>
                <xsl:apply-templates select="STUDENT_REF"/>
                <xsl:apply-templates select="FATHER_NAME"/>
                <xsl:apply-templates select="MOTHER_NAME"/>
                <xsl:apply-templates select="CORE_SUBJECTS"/>
                <xsl:apply-templates select="OPT_SUBJECTS"/>
                <xsl:apply-templates select="STUDENT_KEY"/>
                <xsl:apply-templates select="STUDENT_KEY_CREATION_DATE"/>
                <xsl:apply-templates select="REFRESH_DATE"/>
            </NOTES>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

转换后的需求必须符合确切的映射顺序,并且需要按照男性/女性进行排序。

在这方面的任何帮助将不胜感激。

之前的例子已经解决了。

问候 雷吉。

2 个答案:

答案 0 :(得分:1)

我已经从@helderdarocha改编了下面的样式表:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output indent="yes"/>

    <xsl:strip-space elements="*"/>

    <xsl:variable name="lowercase" select="'abcdefghijklmnopqrstuvwxyz'" />
    <xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />

    <xsl:template match="/">
        <classified date="{STUDENTS_LIST/@dateGenerated}">
            <students>
                <xsl:apply-templates select="STUDENTS_LIST/STUDENTS/MALE|STUDENTS_LIST/STUDENTS/FEMALE"/>
            </students>
        </classified>
    </xsl:template>

    <xsl:template match="*" mode="notes">
        <xsl:value-of select="translate(name(.), $uppercase, $lowercase)"/>
        <xsl:text>: </xsl:text>
        <xsl:choose>
            <xsl:when test="child::text()">
                <xsl:value-of select="child::text()"/>
                <xsl:if test="not(self::REFRESH_DATE)">
                    <xsl:text>, </xsl:text> 
                </xsl:if>
            </xsl:when>
            <xsl:otherwise>
                <xsl:for-each select="*[.!='']">
                    <xsl:value-of select="."/>
                    <xsl:text>, </xsl:text> 
                </xsl:for-each>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="*" mode="tag">
        <xsl:element name="{translate(name(.), $uppercase, $lowercase)}">
            <xsl:choose>
                <xsl:when test="name() = 'DOB'">
                    <year><xsl:value-of select="."/></year>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="."/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:element>
    </xsl:template>

    <xsl:template match="MALE|FEMALE">
        <student>
            <xsl:apply-templates select="STUDENT_ID|F_NAME|M_NAME|L_NAME" mode="tag"/>
            <sex><xsl:value-of select="translate(name(), $uppercase, $lowercase)"/></sex>

            <xsl:if test="*[not(STUDENT_ID|F_NAME|M_NAME|L_NAME|DOB|JOIN_DATE)]">
                <notes>
                    <xsl:apply-templates select="STUDENT_TYPE|STUDENT_REF|FATHER_NAME|MOTHER_NAME|CORE_SUBJECTS|OPT_SUBJECTS|STUDENT_KEY|STUDENT_KEY_CREATION_DATE" mode="notes"/>
                    <xsl:apply-templates select="REFRESH_DATE" mode="notes"/>
                </notes>
            </xsl:if>
            <xsl:apply-templates select="DOB|JOIN_DATE" mode="tag"/>

        </student>
    </xsl:template>


</xsl:stylesheet>

答案 1 :(得分:0)

您可以通过单独提取模板中的文本值来组合节点。这可能是一个注释。它会在每个之后添加一个逗号(last()除外):

<xsl:template match="*" mode="notes">
    <xsl:value-of select="translate(name(.), $uppercase, $lowercase)"/>
    <xsl:text>: </xsl:text>
    <xsl:value-of select="."/>
    <xsl:if test="not(position() = last())">
        <xsl:text>, </xsl:text> 
    </xsl:if>
</xsl:template>

如果您使用的是XSLT 2.0,则可以使用lowercase函数以小写形式创建元素。如果你坚持使用XSLT 1.0,你可以使用translate这两个变量:

<xsl:variable name="lowercase" select="'abcdefghijklmnopqrstuvwxyz'" />
<xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />

在调用者模板中,您可以创建父包装器元素。例如,这将选择一些要在名为&#34; tag&#34;的模板中处理的元素。和模板中的其他人称为&#34; notes&#34;以上。所有注释都将包含在<notes>...</notes>元素中:

<xsl:template match="STUDENT">
    <student>
        <xsl:apply-templates select="STUDENT_ID|F_NAME|M_NAME|L_NAME|DOB|JOIN_DATE" mode="tag"/>

        <xsl:if test="*[not(STUDENT_ID|F_NAME|M_NAME|L_NAME|DOB|JOIN_DATE)]">
            <notes><xsl:apply-templates mode="notes"/></notes>
        </xsl:if>
    </student>
</xsl:template>

您可以使用xsl:element创建代码:

<xsl:template match="*" mode="tag">
    <xsl:element name="{translate(name(.), $uppercase, $lowercase)}">
        <xsl:choose>
            <xsl:when test="name() = 'DOB'">
                 <year><xsl:value-of select="."/></year>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="."/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:element>
</xsl:template>

使用顶级标记<xsl:strip-space elements="*"/>从源中删除空格,您可能非常接近预期的输出。