0

我需要将混合的“标签和文本”XML 拆分为两个“纯”部分:一个部分只有数据标签(任何不是 a或<b>格式标签的标签);o 其他带有“仅文本”(和格式标签)的部分。<i><sup>//text()

输入示例:

  <root>
    Nonono <i>nonon</i> <data1/> <b>nono</b> 
    <data2>nononono <i>no</i>nononon</data2>.
    <data3>blablabla<data4/></data3>
  </root>

输出示例:

  <root>
    <myTags>
       <data1/>
       <data2>nononono <i>no</i>nononon</data2>
       <data3>blablabla<data4/></data3>  
    </myTags>

    <myText>
      Nonono <i>nonon</i> <b>nono</b> 
      nononono <i>no</i>nononon . blablabla
    </myText>
  </root>

用一个更真实的输入进行编辑,

    Nonono <i>nonon</i> <data1/> <b>nono <data66/> </b> 

必须输出

       <data1/><data66/>

这种情况表达的问题有点复杂。它可以发生在任何级别。


在我的 XSLT的xsl:transform核心之下(不工作!),

<xsl:template match="/">
    <root>
    <myTags><xsl:call-template name="copyOnlyTags"/></myTags>
    <myText><xsl:call-template name="copyOnlyTextAndFormat"/></myText>
    </root>
</xsl:template>

<!-- LIB -->

<xsl:template name="copyOnlyTags">
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:for-each select="node()[not(self::text())]">
        <xsl:choose>
          <xsl:when test="count(*)=0">    <!-- terminal -->
            <xsl:copy-of select="."/>
          </xsl:when>
          <xsl:otherwise>        <!-- recurrence -->
            <xsl:call-template name="copyOnlyTags"/>
          </xsl:otherwise>
        </xsl:choose>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

<xsl:template name="copyOnlyTextAndFormat">
        <xsl:for-each select="node()">
        <xsl:choose>
          <xsl:when test="self::text()">
            <xsl:value-of select="."/>
          </xsl:when>
          <xsl:when test="name()='i' or name()='sup' or name()='sub' or name()='b'">
            <xsl:copy-of select="."/><!-- suppose only text into -->
          </xsl:when>
          <xsl:otherwise>        <!-- recurrence -->
            <xsl:call-template name="copyOnlyTextAndFormat"/>
          </xsl:otherwise>
        </xsl:choose>
        </xsl:for-each>
</xsl:template>
4

1 回答 1

1

XSLT 不是要告诉处理器您想要它做什么,而是要说明您想要得到什么结果。

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

  <xsl:template match="root">
    <xsl:copy>
      <myTags>
        <xsl:apply-templates select="node()" mode="data" />
      </myTags>
      <myText>
        <xsl:apply-templates select="node()" mode="format" />
      </myText>
    </xsl:copy>
  </xsl:template>

  <!-- unless stated otherwise, we want no output -->
  <xsl:template match="node()" mode="data" />
  <xsl:template match="node()" mode="format" />

  <!-- DATA MODE: data elements should be copied -->
  <xsl:template match="*[starts-with(name(), 'data')]" mode="data">
    <xsl:copy-of select="." />
  </xsl:template>

  <!-- DATA MODE: format elements should be passed silently -->
  <xsl:template match="*[not(starts-with(name(), 'data'))]" mode="data">
    <xsl:apply-templates select="node()" mode="data" />
  </xsl:template>

  <!-- FORMAT MODE: format elements and text nodes should be copied -->
  <xsl:template match="text() | *[not(starts-with(name(), 'data'))]" mode="format">
    <xsl:copy>
      <xsl:apply-templates select="node()" mode="format" />
    </xsl:copy>
  </xsl:template>

  <!-- FORMAT MODE: data elements should be passed silently -->
  <xsl:template match="*[starts-with(name(), 'data')]" mode="format">
    <xsl:apply-templates select="node()" mode="format" />
  </xsl:template>

</xsl:stylesheet>

为了

<root>
    Nonono <i>nonon</i> <data1/> <b>nono</b> 
    <data2>nononono <i>no</i>nononon</data2>.
    <data3>blablabla<data4/></data3>
</root>

输出是

<root>
  <myTags>
    <data1/>
    <data2>nononono <i>no</i>nononon</data2>
    <data3>blablabla<data4/></data3>
  </myTags>
  <myText>
    Nonono <i>nonon</i>  <b>nono</b> 
    nononono <i>no</i>nononon.
    blablabla
  </myText>
</root>

为了

<root>
    Nonono <i>nonon</i> <data1/> <b>nono <data66/> </b> 
</root>

它产生

<root>
  <myTags>
    <data1/>
    <data66/>
  </myTags>
  <myText>
    Nonono <i>nonon</i>  <b>nono  </b> 
  </myText>
</root>
于 2013-10-22T12:08:46.907 回答