xml - How can I apply a XSLT template to several different elements with the same structure? -


i have scoured google , stack overflow , have been unable find answer this. apologize if duplicate.

i have xml document has nested types; however, several repeating elements appear throughout document different names , parents. when compared xsd, these repeating elements found same type of object, referenced throughout. there 50 different types reference repeating element. how can write 1 template can called inside of each of 50 templates need write don't have duplicate transform each parent type?

for example:

<model1>    <description>desc1</description>    <code>code1</code>    <type>vmo</type>    <model2>      <description>desc1</description>      <code>code1</code>      <type>vmo</type>    </model2>  </model1>  <model3>    <description>desc1</description>    <code>code1</code>    <type>vmo</type>    <model4>      <model5>        <description>desc1</description>        <code>code1</code>        <type>vmo</type>        <model6>          <description>desc1</description>          <code>code1</code>          <type>vmo</type>        </model6>      </model5>      <code>code1</code>      <type>vmo</type>    </model4>  </model3>  <model7>    <description>desc1</description>    <code>code1</code>    <type>vmo</type>    <model8>      <description>desc1</description>      <code>code1</code>      <type>vmo</type>    </model8>  </model7>

in example above instance, model2, model6 , model8 same structure , need apply same transform each element. this:

<xsl:template match="model1">    <xsl:copy>      <!-- maps other elements -->      <xsl:apply-templates select="somespecialfunction(model3)" />    </xsl:copy>  </xsl:template>  <xsl:template match="model5">    <xsl:copy>      <!-- maps other elements -->      <xsl:apply-templates select="somespecialfunction(model6)" />    </xsl:copy>  </xsl:template>  <xsl:template match="model7">    <xsl:copy>      <!-- maps other elements -->      <xsl:apply-templates select="somespecialfunction(model8)" />    </xsl:copy>  </xsl:template>

and transform parent elements. possible?

i know this:

<xsl:template match="model1/model3">    <xsl:copy>      <!-- transfrom type -->      <xsl:apply-templates select="node()|@*" />    </xsl:copy>  </xsl:template>    <xsl:template match="model5/model6">    <xsl:copy>      <!-- transfrom type -->      <xsl:apply-templates select="node()|@*" />    </xsl:copy>  </xsl:template>    <xsl:template match="model7/model8">    <xsl:copy>      <!-- transfrom type -->      <xsl:apply-templates select="node()|@*" />    </xsl:copy>  </xsl:template>

but repeating lot of code. advice?

edit:

i general in original post, sorry that. more concrete example (and in case, 1 of objects have) address , sub types associated them. several different types of elements have address. example, have product element has seller, supplier, re-seller, list of stakeholder each address, etc. each 1 of these addresses has different name.

<product>    <seller>      <businessaddress>...</businessaddress>      <distributionaddress>...</distributionaddress>      <maincontactaddress>...</maincontactaddress>    </seller>    <reseller>      <businessaddress>...</businessaddress>      <storemanageraddress>...</storemanageraddress>      <maincontactaddress>...</maincontactaddress>    </reseller>    <supplier>      <businessaddress>...</businessaddress>      <distributioncenteraddress>...</distributioncenteraddress>      <maincontactaddress>...</maincontactaddress>    </supplier>    <stakeholders>      <entity>        <homeaddress>...</homeaddress>        <workaddress>...</workaddress>        <secondaryaddress>...</secondaryaddress>        <street>...</street>        <crossstreet>...</crossstreet>      </entity>    </stakeholders>  </product>  <surveyrespondents>    <surveyrespondent>      <address>...</address>      <business>...</business>    </surveyrespondent>    <surveyrespondent>      <address>...</address>      <business>...</business>    </surveyrespondent>  </surveyrespondents>

now isn't of elements have addresses, if go approaches have done before have either make list of templates (like mentioned above) or go long list of matches michael.hor257k suggested.

<xsl:template match="address | business | secondaryaddress | workaddress | home | secondaryaddress | businessaddress | ...">    <!-- apply same transform of these -->  </xsl:template>

to compound problem each address made of multiple sub-types: addresscategory, district, zone, street, streettype, postdirection, predirection, etc. each 1 of these types has same structure, run problem of how match against every type. sub types, street, string in places (when used in other elements) , "codetype" in others. if match wind ugly , not done whole document yet:

<xsl:template match="address | business | secondaryaddress | workaddress | home | secondaryaddress | businessaddress | ...">    <!-- apply same transform of these -->  </xsl:template>    <xsl:template match="address/street | business/street | secondaryaddress/street | workaddress/street | home/street | secondaryaddress/street | businessaddress/street | addresstype | district | zone...">    <!-- apply same transform of these -->  </xsl:template>

am stuck hard read, debug, , maintain xslt of better way this?

it's difficult answer question, because it's context - , not providing full context.

in example above instance, model2, model6 , model8 same structure , need apply same transform each element

why don't do:

<xsl:template match="model2 | model6 |  model8">     <!-- apply same transform of these --> </xsl:template> 

note template can applied node parent of model2 and/or model6 and/or model8 (actually, can applied other contexts too, that's not point here).

how can write 1 template can called inside of each of 50 templates need write

are sure need write 50 templates?


re edit:

the alternative to:

<xsl:template match="address | business | secondaryaddress | workaddress | home | secondaryaddress | businessaddress | ...">     <!-- apply same transform of these --> </xsl:template> 

would be:

<xsl:template name="address">     <xsl:param name="address-node" />     <!-- apply transform  --> </xsl:template> 

but have call template explicitly each location address exists, example:

<xsl:template match="seller">     <xsl:copy>         <!-- other code -->         <xsl:call-template name="address">             <xsl:with-param name="address-node" select="businessaddress"/>         </xsl:call-template>         <xsl:call-template name="address">             <xsl:with-param name="address-node" select="distributionaddress"/>         </xsl:call-template>         <xsl:call-template name="address">             <xsl:with-param name="address-node" select="maincontactaddress"/>         </xsl:call-template>         <!-- more code -->     </xsl:copy> </xsl:template>     

possibly, shortened to:

<xsl:template match="seller">     <xsl:copy>         <!-- other code -->         <xsl:call-template name="address">             <xsl:with-param name="address-nodes" select="businessaddress | distributionaddress | maincontactaddress"/>         </xsl:call-template>         <!-- more code -->     </xsl:copy> </xsl:template>    

even so, not sure alternative more attractive original suggestion.