user2005521
user2005521

Reputation: 3

achieving this xslt translation

I have a requirement where i have to convert using xslt, known tags to be replaced, but for any non-identified tags should be put inside a property bag (like in c#) kind of mode. For example. I want to convert the below XML:

<Envelope>
    <body>
        <MyOperation_reply_data>
            <operation_name>1211</operation_name>
            <operation_short_desc>SCAMA</operation_short_desc>
            <operation_long_desc>C4 SCAM PIECE PART ASSEMBLY
            </operation_long_desc>
            <primary_units>UNITS</primary_units>
            <firstAttribute>123</firstAttribute>
            <sampleone>554</sampleone>
            <area>newarea</area>
            <group>samplegroup</group>
            <whatever>uuu</whatever>
        </MyOperation_reply_data>
    </body>
</Envelope>

To this format:

<Envelope>
<Body>
    <OperationInfo OperationName="MyOperation">
        <OperationData>
            <Operation>MyOperation</Operation>
            <ShortDescription>MyDescription</ShortDescription>
            <LongDescription>MyLongDescription</LongDescription>
            <PrimaryUnits>UNITS</PrimaryUnits>
            <Attributes>
                <Attribute Name="firstAttribute" Value="123" />
                <Attribute Name="sampleone" Value="554" />
                <Attribute Name="area" Value="newarea" />
                <Attribute Name="group" Value="samplegroup" />
                <Attribute Name="whatever" Value="uuu" />
            </Attributes>
        </OperationData>
    </OperationInfo>
</Body>

As you could see only the operation, operation long/shortdescription and primaryunits are the recognized tags. anything else i would want to put it in the Attributes list like above. The "other" tags list could grow - so the idea is to put all those other tags into this property bag kind of mode.

the challenge I have is that i am unable to do for-each or identify the "other" tags. I tried selected not(self:: with or statements but didn't help much.

Upvotes: 0

Views: 62

Answers (1)

Daniel Haley
Daniel Haley

Reputation: 52858

In XSLT 1.0 you can use xsl:key to create a "white list" of elements.

XML Input

<Envelope>
    <body>
        <MyOperation_reply_data>
            <operation_name>1211</operation_name>
            <operation_short_desc>SCAMA</operation_short_desc>
            <operation_long_desc>C4 SCAM PIECE PART ASSEMBLY</operation_long_desc>
            <primary_units>UNITS</primary_units>
            <firstAttribute>123</firstAttribute>
            <sampleone>554</sampleone>
            <area>newarea</area>
            <group>samplegroup</group>
            <whatever>uuu</whatever>
        </MyOperation_reply_data>
    </body>
</Envelope>

XSLT 1.0

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

    <xsl:key name="whiteList" match="*[self::primary_units or 
                                       self::operation_name or
                                       self::operation_short_desc or
                                       self::operation_long_desc]" use="name()"/>

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

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

    <xsl:template match="MyOperation_reply_data">
        <OperationInfo OperationName="{operation_name}">
            <OperationData>
                <xsl:apply-templates select="*[key('whiteList',name())]"/>
                <Attributes>
                    <xsl:apply-templates select="*[not(key('whiteList',name()))]"/>                 
                </Attributes>
            </OperationData>
        </OperationInfo>
    </xsl:template>

    <xsl:template match="operation_name">
        <Operation><xsl:apply-templates/></Operation>
    </xsl:template>

    <xsl:template match="operation_short_desc">
        <ShortDescription><xsl:apply-templates/></ShortDescription>
    </xsl:template>

    <xsl:template match="operation_long_desc">
        <LongDescription><xsl:apply-templates/></LongDescription>
    </xsl:template>

    <xsl:template match="primary_units">
        <PrimaryUnits><xsl:apply-templates/></PrimaryUnits>
    </xsl:template>

    <xsl:template match="MyOperation_reply_data/*[not(key('whiteList',name()))]">
        <Attribute name="{name()}" value="{.}"/>
    </xsl:template>

</xsl:stylesheet>

XML Output

<Envelope>
   <Body>
      <OperationInfo OperationName="1211">
         <OperationData>
            <Operation>1211</Operation>
            <ShortDescription>SCAMA</ShortDescription>
            <LongDescription>C4 SCAM PIECE PART ASSEMBLY</LongDescription>
            <PrimaryUnits>UNITS</PrimaryUnits>
            <Attributes>
               <Attribute name="firstAttribute" value="123"/>
               <Attribute name="sampleone" value="554"/>
               <Attribute name="area" value="newarea"/>
               <Attribute name="group" value="samplegroup"/>
               <Attribute name="whatever" value="uuu"/>
            </Attributes>
         </OperationData>
      </OperationInfo>
   </Body>
</Envelope>

Upvotes: 1

Related Questions