【问题标题】:XSLT-based replacements on different nesting levels不同嵌套级别上的基于 XSLT 的替换
【发布时间】:2016-02-14 14:58:27
【问题描述】:

以下是 XML 文档,其中包含不同嵌套级别的关键元素 sr 和 ds:

<doc>
  <p>
    <sr>some text 1</sr>
    <ds>some text 2</ds>
  </p>
  <p>
    <span>
      <sr>some text 3</sr>
      <ds>some text 4</ds>
    </span>
    <span>
      <sr><b>some</b> text 5</sr>
      <ds>some text <sup>6</sup></ds>
    </span>
  </p>
  <td colspan="2">
    <sr><b>some</b> text 7</sr>
    <ds>some text <b>8</b></ds>
  </td>
</doc>

任务是将其按原样输出为 HTML,但如果遇到 &lt;sr&gt; 和 &lt;ds&gt; 元素,请对父元素进行一些修改:

  1. 将sr的内容放入父元素的title属性中,去掉所有嵌套标签;应该只保留纯文本
  2. 将ds元素的内容原封不动地放到父元素的主体中,包含所有的嵌套标签

例如,上面的文档应该是这样的:

<body>
  <p title="some text 1">some text 2</p>
  <p>
    <span title="some text 3">some text 4</span>
    <span title="some text 5">some text <sup>6</sup></span>
  </p>
  <td colspan="2" title="some text 7">some text <b>8</b></td>
</body>

XSLT 可以做到这一点吗?

目前我只知道如何处理像&lt;xsl:for-each select="/level1/level2"&gt; 这样的固定嵌套级别的 XML 元素,或者如何选择不同级别的元素但只选择它们,而我的任务是按原样输出其余部分。

你能提供线索吗?

有时我认为将文档完全读入字符串并在不使用 XSLT 的情况下进行一系列纯字符串替换会更简单。

【问题讨论】:

    标签: xml xslt


    【解决方案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="/doc">
        <body>
            <xsl:apply-templates/>
        </body>
    </xsl:template>
    
    <xsl:template match="sr">
        <xsl:attribute name="title">
            <xsl:value-of select="." />
        </xsl:attribute>
    </xsl:template>
    
    <xsl:template match="ds">
        <xsl:apply-templates/>
    </xsl:template>
    
    </xsl:stylesheet>
    

    请注意,这假定 sr 将始终位于 ds 或任何其他同级元素之前。

    【讨论】:

      【解决方案2】:

      这是一个不管sr 和ds 元素的顺序如何都能工作的解决方案:

      <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:template match="node()[not(self::ds )]|@*">
          <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
        </xsl:template>
      
        <xsl:template match="*[sr and ds]" priority="8">
          <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="title"><xsl:value-of select="sr"/></xsl:attribute>
            <xsl:apply-templates/> 
          </xsl:copy>
        </xsl:template>
        <xsl:template match="/*" priority="9">
          <body>
            <xsl:apply-templates/>
          </body>
        </xsl:template>
        <xsl:template match="sr" priority="10"/>
      </xsl:stylesheet>
      

      应用于所提供 XML 文档的这种变体时(注意sr 和ds 的任意顺序):

      <doc>
        <p>
          <ds>some text 2</ds>
          <sr>some text 1</sr>
        </p>
        <p>
          <span>
            <sr>some text 3</sr>
            <ds>some text 4</ds>
          </span>
          <span>
            <sr><b>some</b> text 5</sr>
            <ds>some text <sup>6</sup></ds>
          </span>
        </p>
        <td colspan="2">
          <ds>some text <b>8</b></ds>
          <sr><b>some</b> text 7</sr>
        </td>
      </doc>
      

      产生想要的正确结果:

      <body>
         <p title="some text 1">some text 2</p>
         <p>
            <span title="some text 3">some text 4</span>
            <span title="some text 5">some text <sup>6</sup>
            </span>
         </p>
         <td colspan="2" title="some text 7">some text <b>8</b>
         </td>
      </body>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-06-21
        • 1970-01-01
        • 1970-01-01
        • 2018-02-12
        • 1970-01-01
        • 2015-02-14
        • 2023-03-02
        相关资源
        最近更新 更多