Xsl 保留输出文本顺序

Xsl Preserving output text order

我正在使用 XSLT 将包含复杂数据结构、自由文本等的 xml 文档转换为 HTML 文档。 我处理的文档可以有或没有结构项目,如果存在结构标签,则可以任意嵌套。数据标签可以指 任何类型的商品,所以我事先不知道 XML 文档的内容。

文档看起来像

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="my.xsl"?>
<doc>
  <elementStructure type="tag">
     The following items are cars: 
    <Car id="12" type="data" value="Ferrari"> this is a sport car.
     <structureLev2 type="tag">
       <Model id="432" value="458" />
      <Rim id="55" value="wheels of car" type="data"> 
      <Tire id="234" value="front" type="data">
       <Note id="33" value="special tire" type="data"/> size of front is less that rear.
       <TypeTire id="44" value="radial tire" type="data"/>
      </Tire>
    </Rim>
     </structureLev2>
   </Car>
  </elementStructure>
  <elementStructure type="tag">
    Other text
    <Car id="22" type="data" value="Ford">
      this is a family car.
      <structureLev2 type="tag">
        <Model id="872" value="Mondeo" />
        <Rim id="45" value="wheels of car" type="data">
          <Tire id="734" value="front" type="data">
            <Note id="63" value="normal tire" type="data"/> spare tire could be replaced by run-flat.
            <TypeTire id="84" value="tubeless tire" type="data"/>
          </Tire>
      </Rim>
    </structureLev2>
    </Car>
  </elementStructure>
</doc>

需要的 HTML 文档应该类似于:

<section>
 Some text....
 <ul>     
  <li>Car - Ferrari (this is a sport car.)</li>
  <li>Rim - wheels of the car:</li>
   <ul>
    <li>Tire - front Note: special tire (size of front is less than rear).</li>
    <li>TypeTire - radial tire
   </ul>
 </ul>
</section>

实际上我不知道这是否是一个好的解决方案,但由于我不知道我的 xml 是否包含结构标签,所以我使用 "switch" 在两个主要选项之间进行选择模板。

<?xml version="1.0"?>
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 <xsl:output method="html"/>
 <xsl:strip-space elements="*"/>
 <xsl:template match="doc">
 <html>
   <body>
    <xsl:choose>
     <xsl:when test="//*[@type='tag']">
       <xsl:call-template name="stuct" />
     </xsl:when>
     <xsl:otherwise>
       <xsl:call-template name="plain" />
     </xsl:otherwise>
    </xsl:choose>
   </body>
 </html>
 </xsl:template>
 <xsl:template match="doc/*[@type='tag']" name="stuct">
  <h3>
   <xsl:value-of select="text()"/>
  </h3>
    <xsl:apply-templates mode="str"/>
 </xsl:template>
 <xsl:template match="doc/*[@type='tag']" mode="str">
  <ul>
   <li>
    <xsl:call-template name="dataElem"/>
    <xsl:apply-templates mode="str"/>
   </li>
  </ul>
 </xsl:template>
 <xsl:template match="doc/*[@type='data']" name="dataElem">
  <xsl:for-each select="descendant::node()[not(@type='tag')]">
   <xsl:value-of select="name(.)"/>: <xsl:value-of select="@value" /> (<xsl:value-of select="text()"/>)<br/>
  </xsl:for-each>
 </xsl:template>
 <xsl:template match="doc/*[@type='data']" name="plain">
    <xsl:call-template name="dataElem" />
  </xsl:template>
 </xsl:stylesheet>

在我遇到的所有问题中,从代码本身开始 :-) 出现的一个问题是关于文本的。我希望标签之间的文本可能只出现一次,并且出现在 "parsed" 元素之后。可能吗?

很难从一个不完整的示例中辨别所需转换的逻辑。此外,我怀疑提供的输出实际上是不正确的——因为没有明显的理由将 "Rim" 提升为“Car”的兄弟,而在原始文档中它是其子项。

也许这样的事情对你有用:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>

<xsl:template match="/">
    <html>
       <body>
            <xsl:apply-templates select="*"/>
        </body>
    </html>
</xsl:template>

<xsl:template match="elementStructure">
    <section>
        <xsl:value-of select="normalize-space(text())"/>
        <ul>
            <xsl:apply-templates select="*"/>
        </ul>
    </section>
</xsl:template>

<xsl:template match="*[@type='data']">
    <li>
        <xsl:value-of select="concat(name(), ' - ', @value)"/>
        <xsl:if test="text()">
            <xsl:value-of select="concat(' (', normalize-space(text()), ')')"/>
        </xsl:if>
        <xsl:if test="descendant::*[@type='data']">
            <ul>
                <xsl:apply-templates select="*"/>
            </ul>
        </xsl:if>
    </li>
</xsl:template>

</xsl:stylesheet>

当应用于您的示例输入时,结果将是:

<html>
   <body>
      <section>The following items are cars:
         <ul>
            <li>Car - Ferrari (this is a sport car.)
               <ul>
                  <li>Rim - wheels of car
                     <ul>
                        <li>Tire - front (size of front is less that rear.)
                           <ul>
                              <li>Note - special tire</li>
                              <li>TypeTire - radial tire</li>
                           </ul>
                        </li>
                     </ul>
                  </li>
               </ul>
            </li>
         </ul>
      </section>
      <section>Other text
         <ul>
            <li>Car - Ford (this is a family car.)
               <ul>
                  <li>Rim - wheels of car
                     <ul>
                        <li>Tire - front (spare tire could be replaced by run-flat.)
                           <ul>
                              <li>Note - normal tire</li>
                              <li>TypeTire - tubeless tire</li>
                           </ul>
                        </li>
                     </ul>
                  </li>
               </ul>
            </li>
         </ul>
      </section>
   </body>
</html>

呈现为: