Search code examples
xmlxsltlocalizationxmldiff

XSL to transform XML filtering out only element and attribute values?


I need to transform the following XML to XML that has the same elements and attributes except for values that can be localized - basically English phrases.

Some of the elements (<footnote>) and attributes are optional (<display_data_type>), and I'd like to be able to do this generically - without having a template for each element. Is that possible?

The ultimate goal is to be able compare the default version of the XML with a localized version, ignoring the localized strings.

For example the following:

<data_schema>
    <field symbol="ACCOUNT" type="string" name="Account Number">
        <validators>
            <maxlength>6</maxlength>
        </validators>
        <description>The account number</description>
        <example>123456</example>
        <default_value></default_value>
    </field>
    <field symbol="POSTAL_CODE" type="string" name="Postal Code">
        <description>Postal Code for account</description>
        <example>22022</example>
        <footnote>Does not apply to certain accounts</footnote>
        <default_value></default_value>
    </field>
    <field symbol="DISCOUNT" type="string" name="Discount Percentage" display_data_type="percentage">
        <description>Descount determined by account</description>
        <example>1.5%</example>
        <default_value></default_value>
    </field>
</data_schema>

would be converted to:

<data_schema>
    <field symbol="ACCOUNT" type="string" name="">
        <validators>
            <maxlength>6</maxlength>
        </validators>
        <description/>
        <example/>
        <default_value/>
    </field>
    <field symbol="POSTAL_CODE" type="string" name="">
        <description/>
        <example/>
        <footnote/>
        <default_value/>
    </field>
    <field symbol="DISCOUNT" type="string" name="" display_data_type="percentage">
        <description/>
        <example/>
        <default_value/>
    </field>
</data_schema>

Solution

  • Here's an example. A template like this, when applied, should create a copy of the tree, minus the text areas and attribute text for attributes that are not symbol or type.

    <xsl:template match="*">
      <xsl:element name="{name()}">
        <xsl:for-each select="@*">
          <xsl:choose>
            <xsl:when test="name() = 'symbol' or name() = 'type'">
              <xsl:copy-of select="."/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:attribute name="{name()}"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:for-each>  
    
        <xsl:apply-templates select="*"/>
      </xsl:element>
    </xsl:template>