如何使用xslt从嵌套标签中分别提取子元素

时间:2019-02-22 06:08:23

标签: xml xslt

我输入的xml代码:

        <pre>
            <title>title of xml</title>
            <em>
            <h2> headings</h2>
            <title>write title here</title>
            <pre>
            <h1>heading h1</h1>
            </pre>
            <pre>
            <li>list here</li>
            </pre>
            </em>
         </pre>

实际输出:

            <div>
            <title>title of xml</title>
            <h2> headings</h2>
            <title>write title here</title>
            <h1>heading h1</h1>
            <li>list here</li>
            </div>

预期输出:

             <div>
                <title>title of xml</title>
             </div>
             <div>
                <h2> headings</h2>
                <title>write title here</title>
              </div>
              <div>
                <h1>heading h1</h1>
              </div>
              <div>
                <li>list here</li>
               </div>

我的xsl代码是:

        <xsl:template match="content/body//pre|em">
                  <xsl:choose>
                     <xsl:when test="pre">
                        <xsl:apply-templates />
                     </xsl:when>
                     <xsl:otherwise>
                        <div>
                           <xsl:apply-templates />
                        </div>
                     </xsl:otherwise>
                  </xsl:choose>
               </xsl:template>
            <xsl:template match="content/body/pre/em/pre">
                  <xsl:apply-templates select="./node()" />
            </xsl:template>

我需要将pre和em标记更改为div标记,并分别提取所有这些div。但是根据我的代码,我可以将所有子元素放在一个div标记中,这并不符合我的期望。请提供一些建议这个。

4 个答案:

答案 0 :(得分:0)

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

    <xsl:template match="pre|em">
        <xsl:apply-templates/>
    </xsl:template>
    <xsl:template match="title">
        <xsl:choose>
            <xsl:when test=" not(preceding::title)">
                <div>
                    <title>
                        <xsl:value-of select="."/>
                    </title>
                </div>
            </xsl:when>
            <xsl:when test="preceding-sibling::*[1][self::h2]">
                <div>
                    <xsl:copy-of select="preceding-sibling::*[1][self::h2]"/>
                    <title><xsl:value-of select="."/></title>
                </div>
            </xsl:when>
        </xsl:choose>
    </xsl:template>
    <xsl:template match="h1">
        <div>
            <h1><xsl:value-of select="."/></h1>
        </div>
    </xsl:template>

    <xsl:template match="li">
        <div>
            <li><xsl:value-of select="."/></li>
        </div>
    </xsl:template>
Try it.

答案 1 :(得分:0)

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

<xsl:template match="title">
    <xsl:choose>
        <xsl:when test=" not(preceding::title)">
            <div>
                <title>
                    <xsl:value-of select="."/>
                </title>
            </div>
        </xsl:when>
        <xsl:when test="preceding-sibling::*[1][self::h2]">
            <div>
                <xsl:copy-of select="preceding-sibling::*[1][self::h2]"/>
                <title><xsl:value-of select="."/></title>
            </div>
        </xsl:when>
    </xsl:choose>
</xsl:template>

<xsl:template match="h1|li">
    <div>
        <xsl:copy-of select="."/>
    </div>
</xsl:template>

<xsl:template match="pre|em">
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="h2"/>

答案 2 :(得分:0)

您可以通过将模板应用于目标节点来实现此目的

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

    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>

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

    <xsl:template match="/pre">
        <div>
            <xsl:apply-templates select="*[not(self::em)]"/>
        </div>
        <xsl:apply-templates select="em"/>
    </xsl:template>

    <xsl:template match="em">
        <div>
            <xsl:copy-of select="*[not(self::pre)]"/>
        </div>
        <xsl:apply-templates select="pre"/>
    </xsl:template>

    <xsl:template match="em/pre">
        <div>
            <xsl:apply-templates/>
        </div>
    </xsl:template>

</xsl:stylesheet>

查看实际情况here

答案 3 :(得分:0)

这是一个grouping问题。在XSLT 2.0中,您可以使用此转换

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/">
        <xsl:for-each-group select="//*"
            group-starting-with="pre|em">
            <div>
                <xsl:apply-templates select="current-group()/(* except (em|pre))" />
            </div>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

此输入

<pre>
    <title>title of xml</title>
    <em>
        <h2> headings</h2>
        <title>write title here</title>
        <pre>
            <h1>heading h1</h1>
        </pre>
        <pre>
            <li>list here</li>
        </pre>
    </em>
</pre>

结果

<div>
   <title>title of xml</title>
</div>
<div>
   <h2> headings</h2>
   <title>write title here</title>
</div>
<div>
   <h1>heading h1</h1>
</div>
<div>
   <li>list here</li>
</div>