xmlxslt

XSLT: sorting objects and preserving comments


I'm using a tool to convert game data to XML but one of said tool's quirks is that it outputs parent code objects alphanumerically instead of numerically, sample output with comments below:

<container format="RTPC" endian="Little">
    <object>
        <object name="root">
            <object name="0"><!-- disables input -->
                <value name="_class" type="string">CInputActionOverride</value>
                <value name="_class_hash" type="int">-1833934533</value>
                <value name="_object_id" type="objectid">26D7913A,0</value>
                <value name="action_list" type="string">Accelerate</value><!-- action name -->
                <value name="activate_event" type="vec_events">death_run_play_cutscene,0x0</value>
            </object>
            <object name="1">
                <value name="_class" type="string">CGameObjectList</value>
                <value name="_class_hash" type="int">-1531974803</value>
                <value name="_object_id" type="objectid">C51129BC,0</value><!-- spawn list ref -->
                <value name="name" type="string">SpawnedVehicleList</value>
                <value name="tags" type="vec_int"/>
            </object>
            <object name="10">
                <value name="_class" type="string">CNavMeshDynamicObstacle</value>
                <value name="_class_hash" type="int">838607288</value>
                <value name="_object_id" type="objectid">F96135EC,0</value>
                <value name="disable_event" type="vec_events"/>
                <value name="enable_event" type="vec_events"/>
                <value name="enabled_from_start" type="int">1</value>
            </object>
            <object name="100">
                <value name="_class" type="string">SAnimationLayerInfo</value>
                <value name="_class_hash" type="int">-786417417</value>
                <value name="_object_id" type="objectid">B2B5BF10,0</value>
                <value name="file" type="string">animations/characters/light_facelayer.al</value><!-- anim path -->
                <value name="layer_index" type="int">1</value>
                <value name="layer_name" type="string">Face</value>
                <value name="name" type="string">AnimationLayerInfoFace</value>
            </object>
            <object name="102">
                <value name="_class" type="string">CSpawnReferencePosition</value>
                <value name="_class_hash" type="int">-1429677905</value>
                <value name="_object_id" type="objectid">1958DDF6,0</value>
                <value name="keep_orientation" type="int">1</value>
                <value name="name" type="string">CSpawnReferencePosition</value>
                <value name="no_create_on_load" type="int">1</value>
                <value name="tags" type="vec_int"/>
            </object>
        </object>
    </object>
</container>

To address this sorting issue, I'm using this slightly modified XSL template that I found:

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

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

    <xsl:template match="object">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates select="*">
                <xsl:sort select="@name" data-type="number" order="ascending"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

This template does the job but another issue I'm facing is that the transformation eats all comments [I'm lead to believe this is default behaviour] and my XSL knowledge is next to non-existent, meaning I'm having difficulty figuring out the code necessary to both sort code objects and keep all comments.


Solution

  • All the comments I see in your example input are children of the " numbered" object elements the need to be sorted.

    Assuming there are no comments that are children of the object whose name is root, you could solve your problem by slightly modifying your template so that instead of:

    <xsl:template match="object">
    

    it reads:

    <xsl:template match="object[@name='root']">
    

    Then only the children of the "root" object will be sorted, and everything else will be copied as is by the identity transform template.