7

Using xslt to interpret the flat xml in the nested xhtml

 3 years ago
source link: https://www.codesd.com/item/using-xslt-to-interpret-the-flat-xml-in-the-nested-xhtml.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Using xslt to interpret the flat xml in the nested xhtml

advertisements

I am attempting to write XSLT that will select immediate-siblings of a certain type, but stop when a different tag is reached.

Here's the Source XML:

<?xml version="1.0"?>
<body>
    <proc>Test</proc>
    <alert>Test1: alert 1</alert>
    <alert>Test1: alert 2</p>
    <para>Test para 1</para>
    <alert>Test2: alert 1</alert>
    <alert>Test2: alert 2</alert>
    <alert>Test2: alert 3</alert>
    <proc>Test</proc>
    <alert>Test3: alert 1</alert>
    <alert>Test3: alert 2</alert>
    <alert>Test3: alert 3</alert>
</html>

Here's the expected result:

<?xml version="1.0" encoding="UTF-8"?>
<body>
    <proc>
        <alert>Test1: alert 1</alert>
        <alert>Test1: alert 2</alert>
    </proc>
    <para>Test para 1</para>
    <alert>Test2: alert 1</alert>
    <alert>Test2: alert 2</alert>
    <alert>Test2: alert 3</alert>
    <proc>
        <alert>Test3: alert 1</alert>
        <alert>Test3: alert 2</alert>
        <alert>Test3: alert 3</alert>
    </proc>
</body>

is this even possible?

Here's my current xsl which isn't doing the trick:

<xsl:template match="proc">
    <xsl:variable name="procedure" select="."/>
    <xsl:apply-templates/>
    <xsl:for-each
     select="following-sibling::alert[preceding-sibling::proc[1] = $procedure]">
        <xsl:apply-templates select="."/>
    </xsl:for-each>
</xsl:template>

<xsl:template match="c:hhtAlert">...</xsl:template>

<xsl:template match="c:hhtPara">...</xsl:template>


Here is an efficient and quite short XSLT 1.0 solution:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kFollowing" match="alert"
     use="generate-id(preceding-sibling::*
                      [
                       self::proc
                      or
                       self::para
                       ]
                        [1]
                          [self::proc]
                    )"/>

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

 <xsl:template match="proc">
  <proc>
   <xsl:apply-templates select="key('kFollowing', generate-id())" mode="copy"/>
  </proc>
 </xsl:template>

 <xsl:template match="alert" mode="copy">
  <xsl:call-template name="identity"/>
 </xsl:template>

 <xsl:template match="alert[preceding-sibling::*
                [
                 self::proc
                or
                 self::para
                ]
                 [1]
                   [self::proc]
               ]"
                              />
</xsl:stylesheet>

when this transformation is applied on the provided XML document (corrected to be well-formed):

<body>
    <proc>Test</proc>
    <alert>Test1: alert 1</alert>
    <alert>Test1: alert 2</alert>
    <para>Test para 1</para>
    <alert>Test2: alert 1</alert>
    <alert>Test2: alert 2</alert>
    <alert>Test2: alert 3</alert>
    <proc>Test</proc>
    <alert>Test3: alert 1</alert>
    <alert>Test3: alert 2</alert>
    <alert>Test3: alert 3</alert>
</body>

the wanted result is produced:

<body>
   <proc>
      <alert>Test1: alert 1</alert>
      <alert>Test1: alert 2</alert>
   </proc>
   <para>Test para 1</para>
   <alert>Test2: alert 1</alert>
   <alert>Test2: alert 2</alert>
   <alert>Test2: alert 3</alert>
   <proc>
      <alert>Test3: alert 1</alert>
      <alert>Test3: alert 2</alert>
      <alert>Test3: alert 3</alert>
   </proc>
</body>

Do note: The use of keys makes this transformation many times faster (in case of many alert siblings) than using the preceding-sibling:: or following-sibling:: axes.

Tags xslt

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK