tags:

views:

26

answers:

1

Hi everyone,

Just a quick question. I have one XML and I was hoping to tranform only a section of it without changing anything else. Here is a quick example of what I am looking to do:

Input:

<?xml version="1.0" encoding="UTF-8"?>
<dita xmlns:ditaarch="http://dita.oasis-open.org/architecture/2005/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../xsd/ditabase.xsd">
    <topic id="abc">
        <title>Sample XML</title>
        <body>
         <section id="a">
            <p> Hello section A </p>
         </section>
         <section id="b">
            <p> General Content </p>
         </section>
         <section id="c">
            <p> Hi thank you for coming from $state </p>
         </section>
        </body>
    </topic>
</dita>

Output

<?xml version="1.0" encoding="UTF-8"?>
<dita xmlns:ditaarch="http://dita.oasis-open.org/architecture/2005/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../xsd/ditabase.xsd">
    <topic id="abc">
        <title>Sample XML</title>
        <body>
         <section id="a">
            <p> Hello section A </p>
         </section>
         <section id="b">
            <p> General Content </p>
         </section>
         <section id="c" audience = "WA">
            <p> Hi thank you for coming from WA </p>
         </section>
             <section id="c" audience = NY">
            <p> Hi thank you for coming from NY </p>
         </section>
             <section id="c" audience = "AL">
            <p> Hi thank you for coming from AL </p>
         </section>
             <section id="c" audience = "GA">
            <p> Hi thank you for coming from GA </p>
         </section>
            ...
            <!--Continue for the rest of the states--> 
            ...
        </body>
    </topic>
</dita>

I am using the XALAN processor if that could help. Thanks a lot in advance :D

+3  A: 

I propose that you change a little bit the format of the XML to make the solurion simpler:

Instead of:

<p> Hi thank you for coming from $state </p>

use:

<p> Hi thank you for coming from <state/> </p>

For this format, the following transformation:

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

 <my:states>
   <state name="WA"/>
   <state name="NY"/>
   <state name="AL"/>
   <state name="GA"/>
 </my:states>

 <xsl:variable name="vStates" select="document('')/*/my:states/*"/>

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

 <xsl:template match="section[descendant::state]">
   <xsl:variable name="vSect" select="."/>

   <xsl:for-each select="$vStates">
     <xsl:apply-templates select="$vSect" mode="generate">
       <xsl:with-param name="pState" select="@name"/>
     </xsl:apply-templates>
   </xsl:for-each>
 </xsl:template>

 <xsl:template match="section" mode="generate">
  <xsl:param name="pState"/>

  <xsl:copy>
   <xsl:copy-of select="@*"/>
   <xsl:attribute name="audience">
    <xsl:value-of select="$pState"/>
   </xsl:attribute>
   <xsl:apply-templates>
    <xsl:with-param name="pState" select="$pState"/>
   </xsl:apply-templates>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="state">
  <xsl:param name="pState"/>
  <xsl:value-of select="$pState"/>
 </xsl:template>
</xsl:stylesheet>

when applied on the (slightly modified) provided XML document:

<dita xmlns:ditaarch="http://dita.oasis-open.org/architecture/2005/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../xsd/ditabase.xsd">
    <topic id="abc">
        <title>Sample XML</title>
        <body>
         <section id="a">
            <p> Hello section A </p>
         </section>
         <section id="b">
            <p> General Content </p>
         </section>
         <section id="c">
            <p> Hi thank you for coming from <state/> </p>
         </section>
        </body>
    </topic>
</dita>

produces the wanted, correct result:

<dita xsi:noNamespaceSchemaLocation="../../../xsd/ditabase.xsd" xmlns:ditaarch="http://dita.oasis-open.org/architecture/2005/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
    <topic id="abc">
        <title>Sample XML</title>
        <body>
         <section id="a">
            <p> Hello section A </p>
         </section>
         <section id="b">
            <p> General Content </p>
         </section>
         <section id="c" audience="WA">
            <p> Hi thank you for coming from WA </p>
         </section>
<section id="c" audience="NY">
            <p> Hi thank you for coming from NY </p>
         </section>
<section id="c" audience="AL">
            <p> Hi thank you for coming from AL </p>
         </section>
<section id="c" audience="GA">
            <p> Hi thank you for coming from GA </p>
         </section>
        </body>
    </topic>
</dita>
Dimitre Novatchev
Thank's a lot! This really helps. The change u suggested is prefectly reasonable. Using $state was just a suggestion nothing concrete!
Bilzac
@Dimitre: Really elegant solution!
Alejandro