📄 jaxpxslt6.html
字号:
<a name="wp65076"> </a><p class="pDefinition">The <code class="cCode"><xsl:text></code> function lets you add any text you want, including whitespace. So, it could conceivably be used to output indentation space. The problem is to vary the <span style="font-style: italic">amount</span> of indentation space. XSLT variables seem like a good idea, but they don't work here. The reason is that when you assign a value to a variable in a template, the value is only known <span style="font-style: italic">within</span> that template (statically, at compile time value). Even if the variable is defined globally, the assigned value is not stored in a way that lets it be dynamically known by other templates at runtime. Once <code class="cCode"><apply-templates/></code> invokes other templates, they are unaware of any variable settings made in other templates. </p><a name="wp65077"> </a><p class="pDefinitionTerm">Parameterized templates</p><a name="wp65078"> </a><p class="pDefinition">Using a "parameterized template" is another way to modify a template's behavior. But determining the amount of indentation space to pass as the parameter remains the crux of the problem! </p><a name="wp65079"> </a><p class="pBody">At the moment, then, there does not appear to be any good way to control the indentation of HTML-formatted output. That would be inconvenient if you needed to display or edit the HTML as plain text. But it's not a problem if you do your editing on the XML form, only use the HTML version for display in a browser. (When you view <code class="cCode">stylizer1c.html</code>, for example, you see the results you expect.)</p><a name="wp65081"> </a><h3 class="pHeading2">Processing the Remaining Structure Elements</h3><a name="wp65082"> </a><p class="pBody">In this section, you'll process the <code class="cCode">LIST</code> and <code class="cCode">NOTE</code> elements that add additional structure to an article. </p><hr><a name="wp65083"> </a><p class="pNote">Note: The sample document described in this section is <code class="cCode"><a href="../examples/jaxp/xslt/samples/article2.xml" target="_blank">article2.xml</a></code>, and the stylesheet used to manipulate it is<code class="cCode"><a href="../examples/jaxp/xslt/samples/article2.xsl" target="_blank"> article2.xsl</a></code>. The result is <code class="cCode"><a href="../examples/jaxp/xslt/samples/stylizer2.html" target="_blank">stylizer2.html</a></code>. (The browser-displayable versions are <code class="cCode"><a href="../examples/jaxp/xslt/samples/article2-xml.html" target="_blank">article2-xml.html</a></code>, <code class="cCode"><a href="../examples/jaxp/xslt/samples/article2-xsl.html" target="_blank">article2-xsl.html</a></code>, and <code class="cCode"><a href="../examples/jaxp/xslt/samples/stylizer2-src.html" target="_blank">stylizer2-src.html</a></code>.)</p><hr><a name="wp65084"> </a><p class="pBody">Start by adding some test data to the sample document:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative"><?xml version="1.0"?><ARTICLE> <TITLE>A Sample Article</TITLE> <SECT>The First Major Section ... </SECT><code class="cCodeBold"> <SECT>The Second Major Section <PARA>This section adds a LIST and a NOTE. <PARA>Here is the LIST: <LIST type="ordered"> <ITEM>Pears</ITEM> <ITEM>Grapes</ITEM> </LIST> </PARA> <PARA>And here is the NOTE: <NOTE>Don't forget to go to the hardware store on your way to the grocery! </NOTE> </PARA> </SECT> </code></ARTICLE> <a name="wp65085"> </a></pre></div><hr><a name="wp65086"> </a><p class="pNote">Note: Although the list and note in the XML file are contained in their respective paragraphs, it really makes no difference whether they are contained or not--the generated HTML will be the same, either way. But having them contained will make them easier to deal with in an outline-oriented editor. </p><hr><a name="wp65087"> </a><h4 class="pHeading3">Modify <PARA> handling</h4><a name="wp65088"> </a><p class="pBody">Next, modify the <code class="cCode">PARA</code> template to account for the fact that we are now allowing some of the structure elements to be embedded with a paragraph:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative"><xsl:template match="PARA"><code class="cCodeStruck"> <p><xsl:apply-templates/></p></code><code class="cCodeBold"> <p> <xsl:apply-templates select="text()|B|I|U|DEF|LINK"/> </p> <xsl:apply-templates select="PARA|LIST|NOTE"/></code></xsl:template><a name="wp65089"> </a></pre></div><a name="wp65090"> </a><p class="pBody">This modification uses the same technique you used for section headings. The only difference is that <code class="cCode">SECT</code> elements are not expected within a paragraph. (However, a paragraph could easily exist inside another paragraph, as quoted material, for example.)</p><a name="wp65091"> </a><h4 class="pHeading3">Process <LIST> and <ITEM> elements</h4><a name="wp65092"> </a><p class="pBody">Now you're ready to add a template to process <code class="cCode">LIST</code> elements:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative"><code class="cCodeBold"> <xsl:template match="LIST"> <xsl:if test="@type='ordered'"> <ol> <xsl:apply-templates/> </ol> </xsl:if> <xsl:if test="@type='unordered'"> <ul> <xsl:apply-templates/> </ul> </xsl:if> </xsl:template></code></xsl:stylesheet><a name="wp65093"> </a></pre></div><a name="wp65094"> </a><p class="pBody">The <code class="cCode"><xsl:if></code> tag uses the <code class="cCode">test=""</code> attribute to specify a boolean condition. In this case, the value of the <code class="cCode">type</code> attribute is tested, and the list that is generated changes depending on whether the value is <code class="cCode">ordered</code> or <code class="cCode">unordered</code>.</p><a name="wp65095"> </a><p class="pBody">The two important things to note for this example are:</p><div class="pSmartList1"><ul class="pSmartList1"><a name="wp65096"> </a><div class="pSmartList1"><li>There is no <code class="cCode">else</code> clause, nor is there a <code class="cCode">return</code> or <code class="cCode">exit</code> statement, so it takes two <code class="cCode"><xsl:if></code> tags to cover the two options. (Or the <code class="cCode"><xsl:choose></code> tag could have been used, which provides case-statement functionality.) </li></div><a name="wp65097"> </a><div class="pSmartList1"><li>Single quotes are required around the attribute values. Otherwise, the XSLT processor attempts to interpret the word <code class="cCode">ordered</code> as an XPath function, instead of as a string.</li></div></ul></div><a name="wp65098"> </a><p class="pBody">Now finish up <code class="cCode">LIST</code> processing by handling <code class="cCode">ITEM</code> elements:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative"><code class="cCodeBold"> <xsl:template match="ITEM"> <li><xsl:apply-templates/> </li> </xsl:template></code></xsl:stylesheet><a name="wp65099"> </a></pre></div><a name="wp65100"> </a><h4 class="pHeading3">Ordering Templates in a Stylesheet</h4><a name="wp65101"> </a><p class="pBody">By now, you should have the idea that templates are independent of one another, so it doesn't generally matter where they occur in a file. So from here on, we'll just show the template you need to add. (For the sake of comparison, they're always added at the end of the example stylesheet.) </p><a name="wp65102"> </a><p class="pBody">Order <span style="font-style: italic">does</span> make a difference when two templates can apply to the same node. In that case, the one that is defined <span style="font-style: italic">last</span> is the one that is found and processed. For example, to change the ordering of an indented list to use lowercase alphabetics, you could specify a template pattern that looks like this: <code class="cCode">//LIST//LIST</code>. In that template, you would use the HTML option to generate an alphabetic enumeration, instead of a numeric one.</p><a name="wp65103"> </a><p class="pBody">But such an element could also be identified by the pattern <code class="cCode">//LIST</code>. To make sure the proper processing is done, the template that specifies <code class="cCode">//LIST</code> would have to appear <span style="font-style: italic">before </span>the template the specifies <code class="cCode">//LIST//LIST</code>.</p><a name="wp65104"> </a><h4 class="pHeading3">Process <NOTE> Elements</h4><a name="wp65105"> </a><p class="pBody">The last remaining structure element is the <code class="cCode">NOTE</code> element. Add the template shown below to handle that.</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative"> <code class="cCodeBold"><xsl:template match="NOTE"> <blockquote><b>Note:</b><br/> <xsl:apply-templates/> </p></blockquote> </xsl:template></code></xsl:stylesheet><a name="wp65106"> </a></pre></div><a name="wp65107"> </a><p class="pBody">This code brings up an interesting issue that results from the inclusion of the <code class="cCode"><br/></code> tag. To be well-formed XML, the tag must be specified in the stylesheet as <code class="cCode"><br/></code>, but that tag is not recognized by many browsers. And while most browsers recognize the sequence <code class="cCode"><br></br></code>, they all treat it like a paragraph break, instead of a single line break.</p><a name="wp65108"> </a><p class="pBody">In other words, the transformation <span style="font-style: italic">must</span> generate a <code class="cCode"><br></code> tag, but the stylesheet must specify <code class="cCode"><br/></code>. That brings us to the major reason for that special output tag we added early in the stylesheet:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative"><xsl:stylesheet ... > <code class="cCodeBold"><xsl:output method="html"/></code> ...</xsl:stylesheet><a name="wp65109"> </a></pre></div><a name="wp65110"> </a><p class="pBody">That output specification converts empty tags like <code class="cCode"><br/></code> to their HTML form, <code class="cCode"><br>,</code> on output. That conversion is important, because most browsers do not recognize the empty tags. Here is a list of the affected tags:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">area frame isindexbase hr linkbasefont img metabr input paramcol<a name="wp78807"> </a></pre></div><a name="wp65136"> </a><p class="pBody">To summarize, by default XSLT produces well-formed XML on output. And since an XSL stylesheet is well-formed XML to start with, you cannot easily put a tag like <code class="cCode"><br></code> in the middle of it. The "<code class="cCode"><xsl:output method="html"/></code>" solves the problem, so you can code <code class="cCode"><br/></code> in the stylesheet, but get <code class="cCode"><br></code> in the output.</p><a name="wp65137"> </a><p class="pBody">The other major reason for specifying <code class="cCode"><xsl:output method="html"/> </code>is that, as with the specification <code class="cCode"><xsl:output method="text"/></code>, generated text is <span style="font-style: italic">not</span> escaped. For example, if the stylesheet includes the <code class="cCode">&lt;</code> entity reference, it will appear as the <code class="cCode"><</code> character in the generated text. When XML is generated, on the other hand, the <code class="cCode">&lt;</code> entity reference in the stylesheet would be unchanged, so it would appear as <code class="cCode">&lt;</code> in the generated text.</p><hr><a name="wp65138"> </a><p class="pNote">Note: If you actually want <code class="cCode">&lt;</code> to be generated as part of the HTML output, you'll need to encode it as <code class="cCode">&amp;lt;</code>--that sequence becomes <code class="cCode">&lt;</code> on output, because only the <code class="cCode">&amp;</code> is converted to an <code class="cCode">&</code> character.</p><hr><a name="wp65139"> </a><h4 class="pHeading3">Run the Program</h4><a name="wp65140"> </a><p class="pBody">
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -