如何使用XSLT将元素提升到父级之上一级?

时间:2015-09-02 12:42:43

标签: xml xslt

我有一个问题,我在他们的fahter元素p中有很多span,我想要的是在p中转换它们,并将它们放在它们的父级中,就像示例代码一样: 初始代码:

<p class="text"><span class="textTitle">Lorem ipsum </span>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim.</p>

<p class="text">Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. Por scientie, musica, sport etc, litot Europa usa li sam vocabular. Li lingues differe solmen in li grammatica, li pronunciation e li plu commun vocabules.</p>

<p class="text"><span class="textTitle">Sed ut perspiciatis </span>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.</p>

结果我希望它是这样的:

<p class="textTitle">Lorem ipsum </p>
<p class="text">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim.</p>

<p class="text">Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. Por scientie, musica, sport etc, litot Europa usa li sam vocabular. Li lingues differe solmen in li grammatica, li pronunciation e li plu commun vocabules.</p>

<p class="textTitle">Sed ut perspiciatis </p>
<p class="text">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.</p>

我可以发布我的xslt,但不能工作:

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

<xsl:template match="//p[contains(@class,'text')]">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="//span[contains(@class,'textTitle')]"/>
    <p class="textTitle"><xsl:apply-template></p>
<xsl:template>

我使用的是xhtml而不是xml,我的doctype是:

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">

2 个答案:

答案 0 :(得分:1)

我已经采用了您的示例代码(这不是正确的XML,所以它不可能用于任何事情,但我修复了它)。如果您按如下方式更改它,它会根据您在问题中提供的信息输出您想要的内容:

<!-- assuming XSLT 1.0, but runs equally well with XSLT 2.0 -->
<xsl:stylesheet version="1.0"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:x="http://www.w3.org/1999/xhtml"
    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
    exclude-result-prefixes="x">

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

    <xsl:template match="x:p[@class = 'text']">
        <xsl:apply-templates select="x:span[@class='textTitle']" />
        <xsl:copy>
            <xsl:copy-of select="@*" />
            <xsl:apply-templates select="node()[not(self::x:span[@class='textTitle'])]" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="x:span[@class='textTitle']">
        <p class="textTitle"><xsl:value-of select="." /></p>
    </xsl:template>

</xsl:stylesheet>

根据您的输入,这会生成以下结果:

<p class="textTitle">Lorem ipsum </p><p class="text">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim.</p>

<p class="text">Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. Por scientie, musica, sport etc, litot Europa usa li sam vocabular. Li lingues differe solmen in li grammatica, li pronunciation e li plu commun vocabules.</p>

<p class="textTitle">Sed ut perspiciatis </p><p class="text">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.</p>

当然,与编程中经常一样,有更多方法可以做到这一点。

请注意您对原始代码的一些评论:

<xsl:template match="//span[contains(@class,'postilla')]"/>

您的示例中没有postilla,因此永远不会命中。此外,使用//开始匹配模式并非违法,但除了对性能有害外,它也没有任何效果。

<xsl:template match="//p[contains(@class,'text')]">

而不是contains(),您可能需要=,例如[@class = 'text']。和上面//的评论相同。

编辑:编辑完成后,很明显您无法处理源代码,这似乎是XHTML。

XHTML中的元素位于命名空间中:http://www.w3.org/1999/xhtml。只需将以下内容添加到主样式表声明:xmlns="http://www.w3.org/1999/xhtml",以便任何文字结果元素都在正确的命名空间中,并添加xmlns:x="http://www.w3.org/1999/xhtml",并在任何XPath表达式或模式中为每个元素名称添加前缀。 / p>

我已更新上面的代码以反映这一点。

注意:如果您使用XSLT 2.0,也可以使用xpath-default-namespace解决此问题。

答案 1 :(得分:1)

这适用于您的示例:

XSLT 1.0

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

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

<xsl:template match="p[@class='text']">
    <xsl:apply-templates select="span[@class='textTitle']"/>
    <xsl:copy>
        <xsl:apply-templates select="@*|node()[not(self::span[@class='textTitle'])]"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="span[@class='textTitle']">
    <p class="textTitle">
        <xsl:apply-templates/>
    </p>
</xsl:template>

</xsl:stylesheet>

我没有在您的输入中看到span[contains(@class,'postilla')]