blob: dbcebf35c0e6eaaff0c88e219f0dea3fc053adec [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="Date-Revision-yyyymmdd" content="20140918"/>
<meta http-equiv="Content-Language" content="en"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>XSL Result</title>
<link href="//fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,400italic,600italic,700italic" rel="stylesheet" type="text/css">
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
<link href="/css/main.css" rel="stylesheet">
<link href="/css/custom.css" rel="stylesheet">
<link href="/css/syntax.css" rel="stylesheet">
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="/bootstrap/js/bootstrap.js"></script>
<script type="text/javascript" src="/js/community.js"></script>
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
/* We explicitly disable cookie tracking to avoid privacy issues */
_paq.push(['disableCookies']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//analytics.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '41']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
</head>
<body>
<a href="https://github.com/apache/struts" class="github-ribbon">
<img decoding="async" loading="lazy" style="position: absolute; right: 0; border: 0;" width="149" height="149" src="https://github.blog/wp-content/uploads/2008/12/forkme_right_red_aa0000.png?resize=149%2C149" class="attachment-full size-full" alt="Fork me on GitHub" data-recalc-dims="1">
</a>
<header>
<nav>
<div role="navigation" class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" data-toggle="collapse" data-target="#struts-menu" class="navbar-toggle">
Menu
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a href="/index.html" class="navbar-brand logo"><img src="/img/struts-logo.svg"></a>
</div>
<div id="struts-menu" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Home<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/index.html">Welcome</a></li>
<li><a href="/download.cgi">Download</a></li>
<li><a href="/releases.html">Releases</a></li>
<li><a href="/announce-2024.html">Announcements</a></li>
<li><a href="http://www.apache.org/licenses/">License</a></li>
<li><a href="https://www.apache.org/foundation/thanks.html">Thanks!</a></li>
<li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
<li><a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy Policy</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Support<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/mail.html">User Mailing List</a></li>
<li><a href="https://issues.apache.org/jira/browse/WW">Issue Tracker</a></li>
<li><a href="/security.html">Reporting Security Issues</a></li>
<li><a href="/commercial-support.html">Commercial Support</a></li>
<li class="divider"></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Migration+Guide">Version Notes</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Security+Bulletins">Security Bulletins</a></li>
<li class="divider"></li>
<li><a href="/maven/project-info.html">Maven Project Info</a></li>
<li><a href="/maven/struts2-core/dependencies.html">Struts Core Dependencies</a></li>
<li><a href="/maven/struts2-plugins/modules.html">Plugin Dependencies</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Documentation<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/birdseye.html">Birds Eye</a></li>
<li><a href="/primer.html">Key Technologies</a></li>
<li><a href="/kickstart.html">Kickstart FAQ</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Home">Wiki</a></li>
<li class="divider"></li>
<li><a href="/getting-started/">Getting Started</a></li>
<li><a href="/security/">Security Guide</a></li>
<li><a href="/core-developers/">Core Developers Guide</a></li>
<li><a href="/tag-developers/">Tag Developers Guide</a></li>
<li><a href="/maven-archetypes/">Maven Archetypes</a></li>
<li><a href="/plugins/">Plugins</a></li>
<li><a href="/maven/struts2-core/apidocs/index.html">Struts Core API</a></li>
<li><a href="/tag-developers/tag-reference.html">Tag reference</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/FAQs">FAQs</a></li>
<li><a href="http://cwiki.apache.org/S2PLUGINS/home.html">Plugin registry</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Contributing<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/youatstruts.html">You at Struts</a></li>
<li><a href="/helping.html">How to Help FAQ</a></li>
<li><a href="/dev-mail.html">Development Lists</a></li>
<li class="divider"></li>
<li><a href="/submitting-patches.html">Submitting patches</a></li>
<li><a href="/builds.html">Source Code and Builds</a></li>
<li><a href="/coding-standards.html">Coding standards</a></li>
<li><a href="/contributors/">Contributors Guide</a></li>
<li class="divider"></li>
<li><a href="/release-guidelines.html">Release Guidelines</a></li>
<li><a href="/bylaws.html">PMC Charter</a></li>
<li><a href="/volunteers.html">Volunteers</a></li>
<li><a href="https://gitbox.apache.org/repos/asf?p=struts.git">Source Repository</a></li>
<li><a href="/updating-website.html">Updating the website</a></li>
</ul>
</li>
<li class="apache"><a href="http://www.apache.org/"><img src="/img/apache.png"></a></li>
</ul>
</div>
</div>
</div>
</nav>
</header>
<article class="container">
<section class="col-md-12">
<a class="edit-on-gh" href="https://github.com/apache/struts-site/edit/master/source/core-developers/xsl-result.md" title="Edit this page on GitHub">Edit on GitHub</a>
<a href="result-types" title="back to Result types"><< back to Result types</a>
<h1 id="xsl-result">XSL Result</h1>
<h2 id="description">Description</h2>
<p>XSLTResult uses XSLT to transform an action object to XML. The recent version has been specifically modified to deal
with Xalan flaws. When using Xalan you may notice that even though you have a very minimal stylesheet like this one</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;xsl:template</span> <span class="na">match=</span><span class="s">"/result"</span><span class="nt">&gt;</span>
<span class="nt">&lt;result/&gt;</span>
<span class="nt">&lt;/xsl:template&gt;</span>
</code></pre></div></div>
<p>Xalan would still iterate through every property of your action and all its descendants.</p>
<p>If you had double-linked objects, Xalan would work forever analysing an infinite object tree. Even if your stylesheet
was not constructed to process them all. It’s because the current Xalan eagerly and extensively converts everything
to its internal DTM model before further processing.</p>
<p>That’s why there’s a loop eliminator added that works by indexing every object-property combination during processing.
If it notices that some object’s property was already walked through, it doesn’t go any deeper. Say you have two objects,
x and y, with the following properties set (pseudocode):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x.y = y;
and
y.x = x;
action.x=x;
</code></pre></div></div>
<p>Due to that modification, the resulting XML document based on x would be:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;result&gt;</span>
<span class="nt">&lt;x&gt;</span>
<span class="nt">&lt;y/&gt;</span>
<span class="nt">&lt;/x&gt;</span>
<span class="nt">&lt;/result&gt;</span>
</code></pre></div></div>
<p>Without it there would be endless <code class="language-plaintext highlighter-rouge">x/y/x/y/x/y/...</code> elements. The <code class="language-plaintext highlighter-rouge">XSLTResult</code> code tries also to deal with the fact
that DTM model is built in a manner that children are processed before siblings. The result is that if there is object
<code class="language-plaintext highlighter-rouge">x</code> that is both set in action’s <code class="language-plaintext highlighter-rouge">x</code> property, and very deeply under action’s a property then it would only appear under
<code class="language-plaintext highlighter-rouge">a</code>, not under <code class="language-plaintext highlighter-rouge">x</code>. That’s not what we expect, and that’s why <code class="language-plaintext highlighter-rouge">XSLTResult</code> allows objects to repeat in various places
to some extent.</p>
<p>Sometimes the object mesh is still very dense and you may notice that even though you have a relatively simple stylesheet,
execution takes a tremendous amount of time. To help you to deal with that obstacle of Xalan, you may attach regexp filters
to elements paths (xpath).</p>
<blockquote>
<p>In your .xsl file the root match must be named <code class="language-plaintext highlighter-rouge">result</code>. This example will output the username by using <code class="language-plaintext highlighter-rouge">getUsername</code> on your action class:</p>
</blockquote>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;xsl:template</span> <span class="na">match=</span><span class="s">"result"</span><span class="nt">&gt;</span>
<span class="nt">&lt;html&gt;</span>
<span class="nt">&lt;body&gt;</span>
Hello <span class="nt">&lt;xsl:value-of</span> <span class="na">select=</span><span class="s">"username"</span><span class="nt">/&gt;</span> how are you?
<span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span>
<span class="nt">&lt;/xsl:template&gt;</span>
</code></pre></div></div>
<p>In the following example the XSLT result would only walk through action’s properties without their children. It would also
skip every property that has <code class="language-plaintext highlighter-rouge">hugeCollection</code> in their name. Element’s path is first compared to <code class="language-plaintext highlighter-rouge">excludingPattern</code> -
if it matches it’s no longer processed. Then it is compared to <code class="language-plaintext highlighter-rouge">matchingPattern</code> and processed only if there’s a match.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"success"</span> <span class="na">type=</span><span class="s">"xslt"</span><span class="nt">&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"stylesheetLocation"</span><span class="nt">&gt;</span>foo.xslt<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"matchingPattern"</span><span class="nt">&gt;</span>^/result/[^/*]$<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"excludingPattern"</span><span class="nt">&gt;</span>.*(hugeCollection).*<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;/result&gt;</span>
</code></pre></div></div>
<p>In the following example the XSLT result would use the action’s user property instead of the action as it’s base document
and walk through it’s properties. The <code class="language-plaintext highlighter-rouge">exposedValue</code> uses an OGNL expression to derive it’s value.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"success"</span> <span class="na">type=</span><span class="s">"xslt"</span><span class="nt">&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"stylesheetLocation"</span><span class="nt">&gt;</span>foo.xslt<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"exposedValue"</span><span class="nt">&gt;</span>${user}<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;/result&gt;</span>
</code></pre></div></div>
<h2 id="parameters">Parameters</h2>
<p>This result type takes the following parameters:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">stylesheetLocation</code> (default) - the location to go to after execution.</li>
<li><code class="language-plaintext highlighter-rouge">location</code> (deprecated) - the same as <code class="language-plaintext highlighter-rouge">stylesheetLocation</code> but it was dropped since Struts 2.5.</li>
<li><code class="language-plaintext highlighter-rouge">encoding</code> - character encoding used in XML, default UTF-8.</li>
<li><code class="language-plaintext highlighter-rouge">parse</code> - <code class="language-plaintext highlighter-rouge">true</code> by default. If set to false, the location param will not be parsed for Ognl expressions.</li>
<li><code class="language-plaintext highlighter-rouge">matchingPattern</code> - a <code class="language-plaintext highlighter-rouge">Pattern</code> that matches only desired elements, by default it matches everything.</li>
<li><code class="language-plaintext highlighter-rouge">excludingPattern</code> - a <code class="language-plaintext highlighter-rouge">Pattern</code> that eliminates unwanted elements, by default it matches none.</li>
</ul>
<p><code class="language-plaintext highlighter-rouge">struts.xml</code> related configuration:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">struts.xslt.nocache</code> - defaults to <code class="language-plaintext highlighter-rouge">false</code>. If set to true, disables stylesheet caching. Good for development, bad for production.</li>
</ul>
<h2 id="examples">Examples</h2>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"success"</span> <span class="na">type=</span><span class="s">"xslt"</span><span class="nt">&gt;</span>foo.xslt<span class="nt">&lt;/result&gt;</span>
</code></pre></div></div>
</section>
</article>
<footer class="container">
<div class="col-md-12">
Copyright &copy; 2000-2022 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
Apache Struts, Struts, Apache, the Apache feather logo, and the Apache Struts project logos are
trademarks of The Apache Software Foundation. All Rights Reserved.
</div>
<div class="col-md-12">Logo and website design donated by <a href="https://softwaremill.com/">SoftwareMill</a>.</div>
</footer>
<script>!function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (!d.getElementById(id)) {
js = d.createElement(s);
js.id = id;
js.src = "//platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
}
}(document, "script", "twitter-wjs");</script>
<script src="https://apis.google.com/js/platform.js" async="async" defer="defer"></script>
<div id="fb-root"></div>
<script>(function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s);
js.id = id;
js.src = "//connect.facebook.net/en_GB/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
</body>
</html>