mirror of
https://github.com/apache/struts.git
synced 2026-08-07 15:46:57 +00:00
WW-4731 Moves detailed description to wiki
This commit is contained in:
@@ -43,162 +43,8 @@ import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: description -->
|
||||
*
|
||||
* 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
|
||||
* <pre>
|
||||
* <xsl:template match="/result">
|
||||
* <result/>
|
||||
* </xsl:template></pre>
|
||||
*
|
||||
* <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>
|
||||
* <pre>
|
||||
* x.y = y;
|
||||
* and
|
||||
* y.x = x;
|
||||
* action.x=x;</pre>
|
||||
*
|
||||
* <p>
|
||||
* Due to that modification, the resulting XML document based on x would be:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* <result>
|
||||
* <x>
|
||||
* <y/>
|
||||
* </x>
|
||||
* </result></pre>
|
||||
*
|
||||
* <p>
|
||||
* Without it there would be endless x/y/x/y/x/y/... elements.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The XSLTResult 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 x that is both set in action's x property, and very deeply
|
||||
* under action's a property then it would only appear under a, not under x.
|
||||
* That's not what we expect, and that's why XSLTResult 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>
|
||||
*
|
||||
* <p>
|
||||
* <b>Note:</b> In your .xsl file the root match must be named <tt>result</tt>.
|
||||
* <br>This example will output the username by using <tt>getUsername</tt> on your
|
||||
* action class:
|
||||
* <pre>
|
||||
* <xsl:template match="result">
|
||||
* <html>
|
||||
* <body>
|
||||
* Hello <xsl:value-of select="username"/> how are you?
|
||||
* </body>
|
||||
* </html>
|
||||
* </xsl:template>
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* In the following example the XSLT result would only walk through action's
|
||||
* properties without their childs. It would also skip every property that has
|
||||
* "hugeCollection" in their name. Element's path is first compared to
|
||||
* excludingPattern - if it matches it's no longer processed. Then it is
|
||||
* compared to matchingPattern and processed only if there's a match.
|
||||
* </p>
|
||||
*
|
||||
* <!-- END SNIPPET: description -->
|
||||
*
|
||||
* <pre><!-- START SNIPPET: description.example -->
|
||||
* <result name="success" type="xslt">
|
||||
* <param name="location">foo.xslt</param>
|
||||
* <param name="matchingPattern">^/result/[^/*]$</param>
|
||||
* <param name="excludingPattern">.*(hugeCollection).*</param>
|
||||
* </result>
|
||||
* <!-- END SNIPPET: description.example --></pre>
|
||||
*
|
||||
* <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 exposedValue uses an ognl expression to derive it's value.
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* <result name="success" type="xslt">
|
||||
* <param name="location">foo.xslt</param>
|
||||
* <param name="exposedValue">user$</param>
|
||||
* </result>
|
||||
* </pre>
|
||||
* *
|
||||
* <b>This result type takes the following parameters:</b>
|
||||
*
|
||||
* <!-- START SNIPPET: params -->
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li><b>location (default)</b> - the location to go to after execution.</li>
|
||||
* <li><b>encoding</b> - character encoding used in XML, default UTF-8.</li>
|
||||
*
|
||||
* <li><b>parse</b> - true by default. If set to false, the location param will
|
||||
* not be parsed for Ognl expressions.</li>
|
||||
*
|
||||
* <!--
|
||||
* <li><b>matchingPattern</b> - Pattern that matches only desired elements, by
|
||||
* default it matches everything.</li>
|
||||
*
|
||||
* <li><b>excludingPattern</b> - Pattern that eliminates unwanted elements, by
|
||||
* default it matches none.</li>
|
||||
* -->
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* <code>struts.properties</code> related configuration:
|
||||
* </p>
|
||||
* <ul>
|
||||
*
|
||||
* <li><b>struts.xslt.nocache</b> - Defaults to false. If set to true, disables
|
||||
* stylesheet caching. Good for development, bad for production.</li>
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <!-- END SNIPPET: params -->
|
||||
* <p>
|
||||
* <b>Example:</b>
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* <!-- START SNIPPET: example -->
|
||||
* <result name="success" type="xslt">foo.xslt</result>
|
||||
* <!-- END SNIPPET: example -->
|
||||
* </pre>
|
||||
*
|
||||
* XSLTResult uses XSLT to transform an action object to XML.
|
||||
*/
|
||||
public class XSLTResult implements Result {
|
||||
|
||||
@@ -233,7 +79,7 @@ public class XSLTResult implements Result {
|
||||
/** Indicates the property name patterns which should be excluded from the xml. */
|
||||
private String excludingPattern;
|
||||
|
||||
/** Indicates the ognl expression respresenting the bean which is to be exposed as xml. */
|
||||
/** Indicates the ognl expression representing the bean which is to be exposed as xml. */
|
||||
private String exposedValue;
|
||||
|
||||
/** Indicates the status to return in the response */
|
||||
@@ -258,8 +104,6 @@ public class XSLTResult implements Result {
|
||||
}
|
||||
|
||||
public void setStylesheetLocation(String location) {
|
||||
if (location == null)
|
||||
throw new IllegalArgumentException("Null location");
|
||||
this.stylesheetLocation = location;
|
||||
}
|
||||
|
||||
@@ -306,12 +150,15 @@ public class XSLTResult implements Result {
|
||||
long startTime = System.currentTimeMillis();
|
||||
String location = getStylesheetLocation();
|
||||
|
||||
if (location == null) {
|
||||
throw new IllegalArgumentException("Parameter 'stylesheetLocation' cannot be null!");
|
||||
}
|
||||
|
||||
if (parse) {
|
||||
ValueStack stack = ActionContext.getContext().getValueStack();
|
||||
location = TextParseUtil.translateVariables(location, stack);
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
HttpServletResponse response = ServletActionContext.getResponse();
|
||||
response.setStatus(status);
|
||||
@@ -331,10 +178,12 @@ public class XSLTResult implements Result {
|
||||
transformer.setErrorListener(buildErrorListener());
|
||||
|
||||
String mimeType;
|
||||
if (templates == null)
|
||||
if (templates == null) {
|
||||
mimeType = "text/xml"; // no stylesheet, raw xml
|
||||
else
|
||||
} else {
|
||||
mimeType = templates.getOutputProperties().getProperty(OutputKeys.MEDIA_TYPE);
|
||||
}
|
||||
|
||||
if (mimeType == null) {
|
||||
// guess (this is a servlet, so text/html might be the best guess)
|
||||
mimeType = "text/html";
|
||||
@@ -383,8 +232,9 @@ public class XSLTResult implements Result {
|
||||
}
|
||||
|
||||
protected AdapterFactory getAdapterFactory() {
|
||||
if (adapterFactory == null)
|
||||
if (adapterFactory == null) {
|
||||
adapterFactory = new AdapterFactory();
|
||||
}
|
||||
return adapterFactory;
|
||||
}
|
||||
|
||||
@@ -428,8 +278,7 @@ public class XSLTResult implements Result {
|
||||
return templates;
|
||||
}
|
||||
|
||||
protected Source getDOMSourceForStack(Object value)
|
||||
throws IllegalAccessException, InstantiationException {
|
||||
protected Source getDOMSourceForStack(Object value) throws IllegalAccessException, InstantiationException {
|
||||
return new DOMSource(getAdapterFactory().adaptDocument("result", value) );
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user