捕获'半'标记的文本

时间:2013-10-04 15:44:29

标签: xml xslt-2.0

抱歉格式化,'长时潜伏,第一次海报'....

我自己和另一位程序员一直在研究这个问题,并尝试了许多排列。我想要捕获的是最后一个'这是条形图外的未标记文本'行... 不知道如何更好地描述标记,但我收到的结构如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <text>
    <inlineTag name="bar">
    <inlineTag name="text">
        <inlineTag name="strong">
            THIS IS A SIDEBAR BOX
        </inlineTag>
    </inlineTag>`
    <break type="paragraph"/>
    <break type="paragraph"/>
    This is untagged text inside bar.
    </inlineTag>
     This is untagged text outside bar
    </text>

我针对这个xslt运行它:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:template name="Untagged_Bar" match="text()[parent::node()/@name='bar']">
    <xsl:choose>
        <xsl:when test="self::text() and string-length(.) &gt; 0">
            <xsl:element name="p">
                <xsl:attribute name="class" select="'k4text'"/>
                <xsl:value-of select="."/>
            </xsl:element>
        </xsl:when>
        <xsl:otherwise>
            <xsl:apply-templates/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
<xsl:template name="bold" match="//inlineTag[@name='strong']">
    <xsl:element name="strong">
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>
<xsl:template match="/">
    <root>
    <xsl:apply-templates/>
    </root>
</xsl:template>

我得到了这个,这几乎是我想要的......

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
     <p class="k4text">
     </p>
     <strong>
      THIS IS A SIDEBAR BOX
      </strong>
      <p class="k4text">
      </p>
    <p class="k4text">
    </p>
    <p class="k4text">
    This is untagged text inside bar.
    </p>
    This is untagged text outside bar
    </root>

我想要的更像是这个:

   <?xml version="1.0" encoding="UTF-8"?>
   <root>
      <p class="k4text">
      <strong>
       THIS IS A SIDEBAR BOX
      </strong>
      </p>
      <p class="k4text">
      This is untagged text inside bar.
      </p>
      <p class="k4text">
      This is untagged text outside bar
      </p>
    </root>

我错过了什么?我在工作中有另一个xslt家伙看看它,我们尝试了很多排列,这是我们可以得到的最接近的,但我们仍然不能最后

   <p class="k4text">
    This is untagged text outside bar
    </p>

出来正确...任何想法/帮助/建议非常感谢!

1 个答案:

答案 0 :(得分:0)

这是我的建议:

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

<xsl:output indent="yes"/>

<xsl:template match="/">
  <root>
    <xsl:apply-templates select="//text()[normalize-space()]"/>
  </root>
</xsl:template>

<xsl:template match="text()">
  <xsl:variable name="current-text" select="."/>
  <xsl:apply-templates select="/*" mode="h">
    <xsl:with-param name="current-text" select="$current-text" tunnel="yes"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="*" mode="h">
  <xsl:param name="current-text" tunnel="yes"/>
  <xsl:apply-templates select="node()[descendant-or-self::node() intersect $current-text]" mode="h"/>
</xsl:template>

<xsl:template match="inlineTag[@name = 'strong']" mode="h">
  <xsl:param name="current-text" tunnel="yes"/>
  <strong>
    <xsl:apply-templates select="node()[descendant-or-self::node() intersect $current-text]" mode="h"/>
  </strong>
</xsl:template>

<xsl:template match="*[@name = 'bar']" mode="h">
  <xsl:param name="current-text" tunnel="yes"/>
  <p class="k4text">
    <xsl:apply-templates select="node()[descendant-or-self::node() intersect $current-text]" mode="h"/>
  </p>
</xsl:template>

<xsl:template match="text()[not(ancestor::*[@name = 'bar'])]" mode="h">
  <p class="k4text">
    <xsl:value-of select="."/>
  </p>
</xsl:template>

</xsl:stylesheet>

它转换输入

<?xml version="1.0" encoding="UTF-8"?>
    <text>
    <inlineTag name="bar">
    <inlineTag name="text">
        <inlineTag name="strong">
            THIS IS A SIDEBAR BOX
        </inlineTag>
    </inlineTag>
    <break type="paragraph"/>
    <break type="paragraph"/>
    This is untagged text inside bar.
    </inlineTag>
     This is untagged text outside bar
    </text>

进入结果

<root>
   <p class="k4text">
      <strong>
            THIS IS A SIDEBAR BOX
        </strong>
   </p>
   <p class="k4text">
    This is untagged text inside bar.
    </p>
   <p class="k4text">
     This is untagged text outside bar
    </p>
</root>

我认为上述解决方案对所有node()[descendant-or-self::node() intersect $current-text]检查都很昂贵。因此,我发布了一种不同的方法,只需在每个文本节点需要重建时计算节点:

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

<xsl:output indent="yes"/>

<xsl:template match="/">
  <root>
    <xsl:apply-templates select="//text()[normalize-space()]"/>
  </root>
</xsl:template>

<xsl:template match="text()">
  <xsl:variable name="nodes" select="ancestor-or-self::node() except /"/>
  <xsl:apply-templates select="$nodes[1]" mode="h">
    <xsl:with-param name="remaining-nodes" select="$nodes[position() gt 1]" tunnel="yes"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="*" mode="h">
  <xsl:param name="remaining-nodes" tunnel="yes"/>
  <xsl:apply-templates select="$remaining-nodes[1]" mode="h">
    <xsl:with-param name="remaining-nodes" select="$remaining-nodes[position() gt 1]" tunnel="yes"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="inlineTag[@name = 'strong']" mode="h">
  <xsl:param name="remaining-nodes" tunnel="yes"/>
  <strong>
    <xsl:apply-templates select="$remaining-nodes[1]" mode="h">
      <xsl:with-param name="remaining-nodes" select="$remaining-nodes[position() gt 1]" tunnel="yes"/>
    </xsl:apply-templates>
  </strong>
</xsl:template>

<xsl:template match="*[@name = 'bar']" mode="h">
  <xsl:param name="remaining-nodes" tunnel="yes"/>
  <p class="k4text">
    <xsl:apply-templates select="$remaining-nodes[1]" mode="h">
      <xsl:with-param name="remaining-nodes" select="$remaining-nodes[position() gt 1]" tunnel="yes"/>
    </xsl:apply-templates>
  </p>
</xsl:template>

<xsl:template match="text()[not(ancestor::*[@name = 'bar'])]" mode="h">
  <p class="k4text">
    <xsl:value-of select="."/>
  </p>
</xsl:template>

</xsl:stylesheet>

输出应该相同,但代码应该更有效。