[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

RE: [xsl] selecting everything below a node


Subject: RE: [xsl] selecting everything below a node
From: Jorg Heymans <Jorg.Heymans@xxxxxxxxxx>
Date: Thu, 7 Aug 2003 11:45:40 +0100

Answering to my own question ... :-)

There was a namespace on the aggregated request document. So instead of
referencing /aggregate/request/etc I did /aggregate/req:request. I didn't
see the namespaces at first because mozilla leaves them out in the browser.

it works perfectly now!

Thanks again Markus.

-----Original Message-----
From: Jorg Heymans [mailto:Jorg.Heymans@xxxxxxxxxx] 
Sent: Donnerstag, 7. August 2003 12:00
To: 'xsl-list@xxxxxxxxxxxxxxxxxxxxxx'
Subject: RE: [xsl] selecting everything below a node

Hi Markus,

Thanks for this solution! I have applied your tips, but in the
replace-one-param function it never gets passed condition
    <!-- Terminate if no more parameters there -->
    <xsl:when test="not(/aggregate/request/parameter[$replace-param])">
      <xsl:value-of select="$input"/>
    </xsl:when>
Even though the xml has several parameter elements under /aggregate/request.

Is it even possible to still access the original root document, even though
my first template goes like
 
<xsl:template match="/" >
  <xsl:apply-templates select="aggregate/content"/>
</xsl:template>

Could this be the problem?


Here is the full template now 

xsl:template match="/" >
  <xsl:apply-templates select="aggregate/content"/>
</xsl:template>


<xsl:template match="node()">

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


<!-- match all attribute values -->
<xsl:template match="@*">
  <xsl:attribute name="{name()}">
	<xsl:call-template name="replace-one-param">
		<xsl:with-param name="input" select="."/>
		<xsl:with-param name="replace-param" select="1"/>
     	</xsl:call-template>
  </xsl:attribute>
</xsl:template>


<xsl:template name="replace-one-param">
  <xsl:param name="input"/>
  <xsl:param name="replace-param"/>
  

  <xsl:choose>
    <!-- Terminate if no more parameters there , this seems always true
somehow -->
    <xsl:when test="not(/aggregate/request/parameter[$replace-param])">
      <xsl:comment><xsl:value-of select="/aggregate/request/
parameter[$replace-param]"/></xsl:comment>
      <xsl:value-of select="$input"/>
    </xsl:when>
    <xsl:otherwise>
      <!-- Replace all occurances of one parameter and store the result in
$tempresult -->
      
      <xsl:variable name="tempresult">
	<xsl:call-template name="substring-replace">
		<xsl:with-param name="search-for"
select="/aggregate/request/parameter[$replace-param]/@name"/>
		<xsl:with-param name="replace-with"
select="/aggregate/request/parameter[$replace-param]/value"/>
		<xsl:with-param name="input" select="$input"/>
     	</xsl:call-template>
      </xsl:variable>
      <!-- Replace the next parameter -->
      <xsl:call-template name="replace-one-param">
		<xsl:with-param name="input" select="$tempresult"/>
		<xsl:with-param name="replace-param"
select="$replace-param+1"/>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<xsl:template name="substring-replace">  
  <xsl:param name="input"/>
  <xsl:param name="search-for"/>
  <xsl:param name="replace-with"/>
  <xsl:message>substring search is :<xsl:value-of
select="$input"/><xsl:value-of select="$search-for"/><xsl:value-of
select="$replace-with"/></xsl:message>
  <xsl:choose>
     <!-- empty search string produces infinite loop -->
     <xsl:when test="$search-for=''">
       <xsl:value-of select="$input"/>
     </xsl:when>
     <xsl:when test="contains($input, $search-for)">
       <xsl:value-of select="substring-before($input, $search-for)"/>
       <xsl:value-of select="$replace-with"/>
       <xsl:call-template name="substring-replace">
          <xsl:with-param name="input"
select="substring-after($input,$search-for)"/>
          <xsl:with-param name="search-for" select="$search-for"/>
          <xsl:with-param name="replace-with" select="$replace-with"/>
       </xsl:call-template>
     </xsl:when>
     <xsl:otherwise>
       <xsl:value-of select="$input"/>
     </xsl:otherwise>
  </xsl:choose>
</xsl:template>



-----Original Message-----
From: Markus Abt [mailto:abt@xxxxxxxx] 
Sent: Mittwoch, 6. August 2003 20:03
To: 'xsl-list@xxxxxxxxxxxxxxxxxxxxxx'
Subject: AW: [xsl] selecting everything below a node

Hi Jorg,

five steps towards the goal:

(1)
Your pattern "aggregate/content//@*" matches two templates. You
want only the second matching template to match, so remove this
pattern from the first template:

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


(2)
You cannot output a comment node directly followed by an attribute node.
Either reverse the order, or use <xsl:message> instead of <xsl:comment>
for debugging:

<!-- match all attribute values -->
<xsl:template match="aggregate/content//@*">
  <xsl:message><xsl:value-of select="."/></xsl:message>
  <xsl:attribute name="{name()}">
  [...]


(3)
You cannot put a comment node into an attribute node.
Use <xsl:message> instead of <xsl:comment> for debugging:

<xsl:template name="substring-replace">  
  <xsl:param name="input"/>
  <xsl:param name="search-for"/>
  <xsl:param name="replace-with"/>
  <xsl:message><xsl:value-of select="$input"/><xsl:value-of
select="$search-for"/><xsl:value-of select="$replace-with"/></xsl:message>
  <xsl:choose>
  [...]


(4)
In you recursive call to the substring-replace template, you have to
set the values for the search-for and replace-with parameters.
In your last template, write:

     <xsl:when test="contains($input, $search-for)">
       <xsl:value-of select="substring-before($input, $search-for)"/>
       <xsl:value-of select="$replace-with"/>
       <xsl:call-template name="substring-replace">
              <xsl:with-param name="search-for" select="$search-for"/>
              <xsl:with-param name="replace-with" select="$replace-with"/>
              <xsl:with-param name="input"
select="substring-after($input,$search-for)"/>
       </xsl:call-template>
     </xsl:when>


(5)
You can loop with another recursive called template to replace one
parameter by the other:

<!-- match all attribute values -->
<xsl:template match="aggregate/content//@*">
  <xsl:message><xsl:value-of select="."/></xsl:message>
  <xsl:attribute name="{name()}">
	<xsl:call-template name="replace-one-param">
		<xsl:with-param name="input" select="."/>
		<xsl:with-param name="replace-param" select="1"/>
     	</xsl:call-template>
  </xsl:attribute>
</xsl:template>

<xsl:template name="replace-one-param">
  <xsl:param name="input"/>
  <xsl:param name="replace-param"/>
  <xsl:choose>
    <!-- Terminate if no more parameters there -->
    <xsl:when test="not(/aggregate/request/parameter[$replace-param])">
      <xsl:value-of select="$input"/>
    </xsl:when>
    <xsl:otherwise>
      <!-- Replace all occurances of one parameter and store the result in
$tempresult -->
      <xsl:variable name="tempresult">
	<xsl:call-template name="substring-replace">
		<xsl:with-param name="search-for"
select="/aggregate/request/parameter[$replace-param]/@name"/>
		<xsl:with-param name="replace-with"
select="/aggregate/request/parameter[$replace-param]"/>
		<xsl:with-param name="input" select="$input"/>
     	</xsl:call-template>
      </xsl:variable>
      <!-- Replace the next parameter -->
      <xsl:call-template name="replace-one-param">
		<xsl:with-param name="input" select="$tempresult"/>
		<xsl:with-param name="replace-param"
select="$replace-param+1"/>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


Putting this all together should make it.

Note, that there are some special cases I did not resolve here.
For example, if one placeholder contains an other placeholder,
then this is replaced if, and only if, the containing placeholder comes
before the contained placeholder in the parameter list.


Regards,
Markus
__________________________
Markus Abt
Comet Computer GmbH
http://www.comet.de



----------
Von: 	Jorg Heymans
Gesendet: 	Mittwoch, 6. August 2003 18:05
An: 	'xsl-list@xxxxxxxxxxxxxxxxxxxxxx'
Betreff: 	RE: [xsl] selecting everything below a node

Hi Markus,

Actually I do want to modify parts.

Given following (a bit more complete now) xml
 
<aggregate>
<request>
<parameter name="placeholder1">textvalue</parameter>
<parameter name="placeholder2">anothertextvalue</parameter>
</request>
<content>
<url src="http://myurl?text=placeholder1"/>
<url src=http://myurl?text=placeholder2"/>
</content>
</aggregate>

I would like to 
- extract the content tree
- for each of the parameter name attributes in the request tree I want to
search the content tree and replace all occurrences of this parameter name
attribute with the parameter value attribute


I think I'm close to the solution though

 
<xsl:template match="/" >
  <xsl:apply-templates select="aggregate/content"/>
</xsl:template>


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


<!-- match all attribute values -->
<xsl:template match="aggregate/content//@*">
  <xsl:comment><xsl:value-of select="."/></xsl:comment>
  <xsl:attribute name="{name()}">
<!-- now here I need to loop over the parameter name attributes and search
each attribute, possibly *slow* -->
	<xsl:call-template name="substring-replace">
		<xsl:with-param name="search-for" select=""/>
		<xsl:with-param name="replace-with" select="blah"/>
		<xsl:with-param name="input" select="."/>
     	</xsl:call-template>
  </xsl:attribute>
  
</xsl:template>



<xsl:template name="substring-replace">  
  <xsl:param name="input"/>
  <xsl:param name="search-for"/>
  <xsl:param name="replace-with"/>
  <xsl:comment><xsl:value-of select="$input"/><xsl:value-of
select="$search-for"/><xsl:value-of select="$replace-with"/></xsl:comment>
  <xsl:choose>
     <!-- empty search string produces infinite loop -->
     <xsl:when test="$search-for=''">
       <xsl:value-of select="$input"/>
     </xsl:when>
     <xsl:when test="contains($input, $search-for)">
       <xsl:value-of select="substring-before($input, $search-for)"/>
       <xsl:value-of select="$replace-with"/>
       <xsl:call-template name="substring-replace">
          <xsl:with-param name="input"
select="substring-after($input,$search-for)"/>
       </xsl:call-template>
     </xsl:when>
     <xsl:otherwise>
       <xsl:value-of select="$input"/>
     </xsl:otherwise>
  </xsl:choose>
</xsl:template>

</xsl:stylesheet>

-----Original Message-----
From: Markus Abt [mailto:abt@xxxxxxxx] 
Sent: Mittwoch, 6. August 2003 17:19
To: 'xsl-list@xxxxxxxxxxxxxxxxxxxxxx'
Subject: AW: [xsl] selecting everything below a node

Hi Jorg,

if you don't want to modify parts of it, you can use:

<xsl:copy-of select="/aggregate/content"/>

Adjust the xpath to your needs.


If you want to modify some nodes, use the identity transformation:

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

Then use specific templates to do the modifications.


Regards,
Markus
__________________________
Markus Abt
Comet Computer GmbH
http://www.comet.de


----------
Von: 	Jorg Heymans
Gesendet: 	Mittwoch, 6. August 2003 16:43
An: 	'xsl-list@xxxxxxxxxxxxxxxxxxxxxx'
Betreff: 	[xsl] selecting everything below a node

Hi list,
 
Given following xml
 
<aggregate>
<request>
many children here
</request>
<content>
.many children here
</content>
</aggregate>
 
How do I extract the whole <content> tree (nodes + attributes) into a
different document?
 
 
Regards
Jorg

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list



Current Thread
Keywords