开发者

Convert the first HTML table row into a heading row for each table using XSLT

开发者 https://www.devze.com 2023-02-09 07:59 出处:网络
I have some html content inside my XML. Previously I could just use <xsl:copy-of select=\"customFields/customField[@name=\'mainContent\']/html\"/> to pull the content into the correct area. A ne

I have some html content inside my XML. Previously I could just use <xsl:copy-of select="customFields/customField[@name='mainContent']/html"/> to pull the content into the correct area. A new requirement is to convert the first <tr> inside each table's <tbody> into a set of thead/tr/th.

I am confused on how to convert, in fact not even shore where to start:

...

<customField name="mainContent" type="Html">
    <html>
        <h1>Page Heading</h1>
        <p>Gusto te minim tempor elit quam. Dolore vel accumsan parum option me. Demonstraverunt congue nisl soluta tincidunt seacula. Soluta saepius de开发者_Python百科monstraverunt praesent claritatem mutationem. Modo te ullamcorper vel augue veniam. Nunc investigationes dolor iriure typi in.</p>
        <p>Gusto te minim tempor elit quam. Dolore vel accumsan parum option me. Demonstraverunt congue nisl soluta tincidunt seacula. Soluta saepius demonstraverunt praesent claritatem mutationem. Modo te ullamcorper vel augue veniam. Nunc investigationes dolor iriure typi in.</p>
        <table cellspacing="0" cellpadding="0" summary="" border="0">
            <tbody>
                <tr>
                    <td>Heading 1</td>
                    <td>Heading 2</td>
                    <td>Heading 3</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>sample</td>
                    <td>sample</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>sample</td>
                    <td>sample</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>sample</td>
                    <td>sample</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>sample</td>
                    <td>sample</td>
                </tr>
            </tbody>
        </table>
    </html>
</customField>
...

into:

...
<customField name="mainContent" type="Html">
    <html>
        <h1>Page Heading</h1>
        <p>Gusto te minim tempor elit quam. Dolore vel accumsan parum option me. Demonstraverunt congue nisl soluta tincidunt seacula. Soluta saepius demonstraverunt praesent claritatem mutationem. Modo te ullamcorper vel augue veniam. Nunc investigationes dolor iriure typi in.</p>
        <p>Gusto te minim tempor elit quam. Dolore vel accumsan parum option me. Demonstraverunt congue nisl soluta tincidunt seacula. Soluta saepius demonstraverunt praesent claritatem mutationem. Modo te ullamcorper vel augue veniam. Nunc investigationes dolor iriure typi in.</p>
        <table cellspacing="0" cellpadding="0" summary="" border="0">
            <thead>
                <tr>
                    <th>Heading 1</th>
                    <th>Heading 2</th>
                    <th>Heading 3</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>sample</td>
                    <td>sample</td>
                    <td>sample</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>sample</td>
                    <td>sample</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>sample</td>
                    <td>sample</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>sample</td>
                    <td>sample</td>
                </tr>
            </tbody>
        </table>
    </html>
</customField>
...


I have some html content inside my XML. Previously I could just use <xsl:copy-of select="customFields/customField[@name='mainContent']/html"/> to pull the content into the correct area. A new requirement is to convert the first <tr> inside each table's <tbody> into a set of thead/tr/th.

This transformation:

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

 <xsl:template match="tbody/tr[1]">
  <thead>
    <tr>
      <xsl:apply-templates/>
    </tr>
  </thead>
 </xsl:template>

 <xsl:template match="tbody/tr[1]/td">
  <th><xsl:apply-templates/></th>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<customField name="mainContent" type="Html">
    <html>
        <h1>Page Heading</h1>
        <p>Gusto te minim tempor elit quam. Dolore vel accumsan parum option me. Demonstraverunt congue nisl soluta tincidunt seacula. Soluta saepius demonstraverunt praesent claritatem mutationem. Modo te ullamcorper vel augue veniam. Nunc investigationes dolor iriure typi in.</p>
        <p>Gusto te minim tempor elit quam. Dolore vel accumsan parum option me. Demonstraverunt congue nisl soluta tincidunt seacula. Soluta saepius demonstraverunt praesent claritatem mutationem. Modo te ullamcorper vel augue veniam. Nunc investigationes dolor iriure typi in.</p>
        <table cellspacing="0" cellpadding="0" summary="" border="0">
            <tbody>
                <tr>
                    <td>Heading 1</td>
                    <td>Heading 2</td>
                    <td>Heading 3</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>sample</td>
                    <td>sample</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>sample</td>
                    <td>sample</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>sample</td>
                    <td>sample</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>sample</td>
                    <td>sample</td>
                </tr>
            </tbody>
        </table>
    </html>
</customField>

produces exactly the wanted, correct result:

<customField name="mainContent" type="Html">
   <html>
      <h1>Page Heading</h1>
      <p>Gusto te minim tempor elit quam. Dolore vel accumsan parum option me. Demonstraverunt congue nisl soluta tincidunt seacula. Soluta saepius demonstraverunt praesent claritatem mutationem. Modo te ullamcorper vel augue veniam. Nunc investigationes dolor iriure typi in.</p>
      <p>Gusto te minim tempor elit quam. Dolore vel accumsan parum option me. Demonstraverunt congue nisl soluta tincidunt seacula. Soluta saepius demonstraverunt praesent claritatem mutationem. Modo te ullamcorper vel augue veniam. Nunc investigationes dolor iriure typi in.</p>
      <table cellspacing="0" cellpadding="0" summary="" border="0">
         <tbody>
            <thead>
               <tr>
                  <th>Heading 1</th>
                  <th>Heading 2</th>
                  <th>Heading 3</th>
               </tr>
            </thead>
            <tr>
               <td>sample</td>
               <td>sample</td>
               <td>sample</td>
            </tr>
            <tr>
               <td>sample</td>
               <td>sample</td>
               <td>sample</td>
            </tr>
            <tr>
               <td>sample</td>
               <td>sample</td>
               <td>sample</td>
            </tr>
            <tr>
               <td>sample</td>
               <td>sample</td>
               <td>sample</td>
            </tr>
         </tbody>
      </table>
   </html>
</customField>

Do note:

The "overriden identity rule" design pattern is used. This is the most fundamental and powerful XSLT design pattern.

UPDATE:

As noticed by Flynn1179, the OP's definition of the problem (above) is inconsistent with the output he provides as wanted result. In this output not only is the first tr inside of the tbody converted to thead/tr (and its td children to th), but the thead is moved outside of the tbody.

In case this is really what the OP wants, here is modified solution also for this case:

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

 <xsl:template match="tbody/tr[1]">
  <thead>
   <tr>
    <xsl:apply-templates/>
   </tr>
  </thead>
  <tbody>
   <xsl:apply-templates 
        select="following-sibling::tr"/>
  </tbody>
 </xsl:template>

 <xsl:template match="tbody/tr[1]/td">
  <th>
   <xsl:apply-templates/>
  </th>
 </xsl:template>

 <xsl:template match="tbody">
  <xsl:apply-templates select="tr[1]"/>
 </xsl:template>
</xsl:stylesheet>

when applied on the same XML document, the result is:

<customField name="mainContent" type="Html">
   <html>
      <h1>Page Heading</h1>
      <p>Gusto te minim tempor elit quam. Dolore vel accumsan parum option me. Demonstraverunt congue nisl soluta tincidunt seacula. Soluta saepius demonstraverunt praesent claritatem mutationem. Modo te ullamcorper vel augue veniam. Nunc investigationes dolor iriure typi in.</p>
      <p>Gusto te minim tempor elit quam. Dolore vel accumsan parum option me. Demonstraverunt congue nisl soluta tincidunt seacula. Soluta saepius demonstraverunt praesent claritatem mutationem. Modo te ullamcorper vel augue veniam. Nunc investigationes dolor iriure typi in.</p>
      <table cellspacing="0" cellpadding="0" summary="" border="0">
         <thead>
            <tr>
               <th>Heading 1</th>
               <th>Heading 2</th>
               <th>Heading 3</th>
            </tr>
         </thead>
         <tbody>
            <tr>
               <td>sample</td>
               <td>sample</td>
               <td>sample</td>
            </tr>
            <tr>
               <td>sample</td>
               <td>sample</td>
               <td>sample</td>
            </tr>
            <tr>
               <td>sample</td>
               <td>sample</td>
               <td>sample</td>
            </tr>
            <tr>
               <td>sample</td>
               <td>sample</td>
               <td>sample</td>
            </tr>
         </tbody>
      </table>
   </html>
</customField>


Try this:

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

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

 <xsl:template match="tbody">
   <xsl:element name="thead">
     <xsl:apply-templates select="tr[1]" />
   </xsl:element>
   <xsl:element name="tbody">
     <xsl:apply-templates select="tr[position()!=1]" />
   </xsl:element>
 </xsl:template>

 <xsl:template match="tr[1]/td">
   <xsl:element name="th">
     <xsl:apply-templates />
   </xsl:element>
 </xsl:template>

</xsl:stylesheet>

It simply replaces your existing tbody element with a thead containing the first row, and a tbody containing all but the first, and then replaces all td elements in the first tr with th instead.


Just for fun, this stylesheet:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="tbody">
        <xsl:apply-templates mode="header"/>
        <xsl:call-template name="identity"/>
    </xsl:template>
    <xsl:template match="tr[1]"/>
    <xsl:template match="tr" mode="header"/>
    <xsl:template match="tr[1]" mode="header">
        <thead>
            <xsl:call-template name="identity"/>
        </thead>
    </xsl:template>
    <xsl:template match="tr[1]/td">
        <th>
            <xsl:apply-templates select="node()|@*"/>
        </th>
    </xsl:template>
</xsl:stylesheet>

Output:

<customField name="mainContent" type="Html">
    <html>
        <h1>Page Heading</h1>
        <p>Gusto te minim tempor elit quam. Dolore vel accumsan parum option me. Demonstraverunt congue nisl soluta tincidunt seacula. Soluta saepius demonstraverunt praesent claritatem mutationem. Modo te ullamcorper vel augue veniam. Nunc investigationes dolor iriure typi in.</p>
        <p>Gusto te minim tempor elit quam. Dolore vel accumsan parum option me. Demonstraverunt congue nisl soluta tincidunt seacula. Soluta saepius demonstraverunt praesent claritatem mutationem. Modo te ullamcorper vel augue veniam. Nunc investigationes dolor iriure typi in.</p>
        <table cellspacing="0" cellpadding="0" summary="" border="0">
            <thead>
                <tr>
                    <th>Heading 1</th>
                    <th>Heading 2</th>
                    <th>Heading 3</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>sample</td>
                    <td>sample</td>
                    <td>sample</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>sample</td>
                    <td>sample</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>sample</td>
                    <td>sample</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>sample</td>
                    <td>sample</td>
                </tr>
            </tbody>
        </table>
    </html>
</customField>
0

精彩评论

暂无评论...
验证码 换一张
取 消