【问题标题】:XSLT "Move" sibling content into closed preceding-siblingXSLT 将同级内容“移动”到封闭的前同级中
【发布时间】:2017-07-31 16:02:37
【问题描述】:

我的输入有一些我想修复的不合格标记,例如

<ul>
  <li>
  </li>
  <p>This is the first bullet item</p>
  <li>
  </li>
  <p>This is the second bullet item</p>
</ul>
...
<ul>
  <li>I am fine. No need to monkey with me.</li>
<ul>

应该是

<ul>
  <li>This is the first bullet item</li>
  <li>This is the second bullet item</li>
</ul>
...
<ul>
  <li>I am fine. No need to monkey with me.</li>
<ul>

我知道如何“解开”p 元素

<xsl:template match="p[parent::ul and preceding-sibling::li]">
    <!-- Don't wrap or copy. Just process content. -->
    <xsl:apply-templates/>
</xsl:template>

但我不知道如何让解包的ps 的内容出现在输出的lis 中。不知何故,我猜,我需要识别空的lis,而不是创建一个新的li,然后添加以下兄弟p 的内容。类似的东西

<xsl:template match="li[not(li) and not(normalize-space())]">
    <li>
        <!-- how do I get content of following-sibling p here?? -->
        <xsl:apply-templates/>
    </li>
</xsl:template>

但这(显然)不起作用。我被卡住了,找不到解决方案。有什么建议吗?

【问题讨论】:

    标签: xslt xslt-1.0


    【解决方案1】:

    不知何故,我猜,我需要识别空的 lis,而不是创建一个新的 li,然后添加以下兄弟 p 的内容。

    这似乎是个好主意,所以试试这个:

    <xsl:template match="li[normalize-space(text())='']">
      <xsl:copy>
        <xsl:value-of select="following-sibling::p[1]/text()" />
      </xsl:copy>
    </xsl:template>
    

    这将使用以下 p 元素的 text() 填充空的 li 元素。

    为了摆脱p 元素,(在某种程度上)反转XPath 表达式并将其放入一个空模板中:

    <xsl:template match="p[normalize-space(preceding-sibling::li[1]/text())='']" />
    

    然后输出为:

    <ul>
      <li>This is the first bullet item</li>
      <li>This is the second bullet item</li>
    </ul>
    

    【讨论】:

    • 这让我走上了正轨,但由于某种原因,如果我使用上面的&lt;xsl:copy&gt;,结果标记为&lt;li/&gt;The text from the following sibling.&lt;li&gt; 也不起作用。结果相同。只有当我将&lt;xsl:copy&gt; 替换为&lt;li class="whatever"&gt; 时,它才会按预期实际出现在标记中。奇数。
    【解决方案2】:

    你为什么不简单地做:

    <xsl:template match="ul">
        <xsl:copy>
            <xsl:for-each select="li">
                <xsl:copy>
                    <xsl:value-of select="following-sibling::p[1]" />
                </xsl:copy>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
    

    或者,如果您愿意:

    <xsl:template match="ul">
        <xsl:copy>
            <xsl:for-each select="p">
                <li>
                    <xsl:apply-templates/>
                </li>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
    

    针对已编辑的问题添加:

    如果这个问题只影响到部分ul节点,可以通过改变来限制模板:

    <xsl:template match="ul">
    

    到:

    <xsl:template match="ul[p]">
    

    或:

    <xsl:template match="ul[li[not(normalize-space())]]">
    

    【讨论】:

    • 抱歉不清楚。一些 &lt;li&gt; 标记不符合要求 - 仅包含空格,后跟同级 &lt;p&gt; - 不是全部。
    • 请编辑您的问题并展示更具代表性的示例。
    • 完成。感谢您的建议。
    • 这仍然模棱两可。您是否有两种类型的ul,其中每个li 都遵循相同的模式?还是可以在同一个ul 中混合使用两种li 类型?
    • 示例现在代表输入。有些uls 可以,有些li 是空的,然后是p。我无法控制输入。谢谢。
    猜你喜欢
    • 2012-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-30
    相关资源
    最近更新 更多