XSLT template overrides

I have a small question regarding overriding an XSLT template. For this segment of my XML:

<record>
  <medication>
    <medicine>
      <name>penicillin G</name>
      <strength>500 mg</strength>
    </medicine>
  </medication>
</record>

      

In my XSLT sheet, I have two templates in the following order:

 <xsl:template match="medication">
   <xsl:copy-of select="." />
   </xsl:template>
   <xsl:template match="medicine/name">
   <text>!unauthorized information!</text>
 </xsl:template>

      

What I want to do is copy everything under the medication element into an output other than the "name" element (or whatever element I explicitly define). The final xml will be shown to the user in RAW XML format. In other words, I want:

<record>
  <medication>
    <medicine>
      <text>! unauthorized information!</text>
      <strength>500 mg</strength>
    </medicine>
  </medication>
</record>

      

Whereas I get the same XML as the input, i.e. without replacing the element with text. Any ideas why matching the second pattern doesn't override the name element in the first one? thanks in advance

- Ali

+1


a source to share


2 answers


Ordering a template does not matter. The only case where this is considered possible (and it depends on the processor) is when you have an unresolved conflict, i.e. an error condition. In this case, the XSLT processor can correct the error by choosing the one that comes last. However, you should never write code that depends on this behavior.

. , <medication>

<name>

. , . , <name>

. <xsl:copy-of select="."/>

<medication>

, : " <medication>

". , -, - ( <xsl:apply-templates/>

.

The solution I have for you is basically the same as alamar, except that it uses a separate processing mode that isolates the rules from all other rules in your stylesheet. Generic pattern match="@* | node()"

causes pattern rules to be recursively applied to children (and attributes), giving you the ability to override behavior for specific nodes.

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <!-- ...placeholder for the rest of your code... -->
  <xsl:template match="/record">
    <record>
      <xsl:apply-templates/>
    </record>
  </xsl:template>
  <!-- end of placeholder -->

  <xsl:template match="medication">
    <!-- Instead of copy-of, whose behavior is to always perform
         a deep copy and cannot be customized, define your own
         processing mode. Rules with this mode name are isolated
         from the rest of your code. -->
    <xsl:apply-templates mode="copy-medication" select="."/>
  </xsl:template>

          <!-- By default, copy all nodes and their descendants -->
          <xsl:template mode="copy-medication" match="@* | node()">
            <xsl:copy>
              <xsl:apply-templates mode="copy-medication" select="@* | node()"/>
            </xsl:copy>
          </xsl:template>

          <!-- But replace <name> -->
          <xsl:template mode="copy-medication" match="medicine/name">
            <text>!unauthorized information!</text>
          </xsl:template>

</xsl:stylesheet>

      



The rule for " medicine/name

" overrides the rule for " @* | node()

" because the template format (which contains " /

") makes the default priority (0.5) higher than the default priority for " node()

" (-1.0).

A complete but short description of how the template works can be found in How XSLT Works on my website.

Finally, I noticed that you mentioned that you want to display "RAW XML" to the user. Does this mean that you want to display, for example, XML with all start and end tags in the browser? In this case, you will need to avoid markup (eg " &lt;

" for " <

"). Check out the XML-to-string utility on my website. Let me know if you need an example on how to use it.

+5


a source


Add to

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

      

to your <xsl:template match="medicine/name">



And delete it <xsl:template match="medication">

altogether!

<?xml version="1.0" encoding="windows-1251"?>
<xsl:stylesheet
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="1.0">

 <xsl:template match="medicine/name">
   <text>!unauthorized information!</text>
 </xsl:template>

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

</xsl:stylesheet>

      

+2


a source







All Articles