基于子节点的检测创建新节点

时间:2012-12-06 10:33:54

标签: xslt

我上一篇文章的反馈很有魅力,但我在系统中遇到了一些文件。输出如下。

<par def='1'>
   <run>This is start of line one para one </run>
   <run>text hotspot 1</run>
   <run> remainder of line one<break/></run>

   <run>This is line 2 </run>
   <run>another hotspot </run>
   <run>remainder of line 2 <break/></run>
 </par>

是否可以使用XSLT生成以下输出?

<document>
   <para>This is start of line one para one text hotspot 1 remainder of line one</para>

   <para>This is line 2 another hotspot remainder of line 2</para>
</document>

即,<break/>节点表示句子的结尾,但句子可能会在几个<run>个节点上运行。

如果有人想知道,源数据是以Lotus Notes的DXL架构格式生成的。

到目前为止,我一直在使用第三方工具生成我的XSLT,我很乐意提供代码,但它不是很干净。

提前再次感谢您,成为此论坛的忠实粉丝。

DONO

3 个答案:

答案 0 :(得分:1)

这个怎么样?它只会为<para>中的第一个<run>创建新的<par>元素,如果前一个<par>中有<break>

<xsl:template match="par">
  <xsl:for-each select="run[preceding-sibling::run[1]/break or not(preceding-sibling::run)]">
    <para>
      <xsl:apply-templates select="."/>
    </para>
  </xsl:for-each>
</xsl:template>

<xsl:template match="run">
  <xsl:value-of select="."/>
  <xsl:if test="not(break)">
    <xsl:apply-templates select="following-sibling::run[1]"/>
  </xsl:if>
</xsl:template>

答案 1 :(得分:1)

虽然不是一种更好的方法,但它可以按你的方式工作..

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

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

  <xsl:template match="par">
    <document>
      <para>
        <xsl:apply-templates select="node()"/>
      </para>
    </document>
  </xsl:template>

  <xsl:template match="run">
    <xsl:value-of select="."/>
    <xsl:apply-templates select="break"/>
  </xsl:template>

  <xsl:template match="break">
    <xsl:value-of select="'&#60;/para&#62;'" disable-output-escaping="yes"/>
    <xsl:value-of select="'&#60;para&#62;'" disable-output-escaping="yes"/>
  </xsl:template>
</xsl:stylesheet>

答案 2 :(得分:0)

此转化

<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="kPreceding" match="run"
      use="generate-id((following::break|descendant::break)[1])"/>

 <xsl:template match="par">
     <document>
      <xsl:apply-templates select="run/break"/>
     </document>
 </xsl:template>

 <xsl:template match="break">
  <para><xsl:apply-templates select="key('kPreceding', generate-id())/text()"/></para>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档时:

<par def='1'>
    <run>This is start of line one para one </run>
    <run>text hotspot 1</run>
    <run> remainder of line one<break/></run>

    <run>This is line 2 </run>
    <run>another hotspot </run>
    <run>remainder of line 2<break/></run>
</par>

会产生想要的正确结果:

<document>
   <para>This is start of line one para one text hotspot 1 remainder of line one</para>
   <para>This is line 2 another hotspot remainder of line 2</para>
</document>

<强>解释

这是典型的XSLT 1.0位置分组解决方案。我们使用密钥来表达break元素与其标识为组的所有run元素之间的关系。