重新排列层次结构 - 将所有显示为元素 para 的后续兄弟元素的 <list>(及其内容)移动到 para

问题描述 投票:0回答:1

我需要重新排列层次结构。将出现在段落之后的列表(及其内容)移动到段落内部(如下同级),同时将其余数据保留在当前位置。

备注:

  • DTD 允许 para 包含列表,列表也可以包含 para
  • DTD 非常复杂,很难为其中出现的所有元素编写匹配语句
  • 该段落后面可能有多个列表需要移动到前一个段落的末尾

我对 XSL 比较陌生,不确定如何处理这个问题,因为它们目前是兄弟姐妹

我还没有尝试任何事情,因为我不知道如何解决这个问题。

谢谢

输入:

<section>
<para updated="20240206"><para.text>This is some para text.</para.text></para>
<para updated="20240206"><para.text>This is some para text with a list following:</para.text></para>
<list updated="20240206">
    <heading>
      <name>List 1</name>
   </heading>
   <list.item updated="20240206"><designator>1)</designator>
   <para><para.text>content of the list item</para.text></para>
   </list.item>
   <list.item updated="20240206"><designator>2)</designator>
   <para><para.text>content of the list item</para.text></para>
   </list.item>
   <list.item updated="20240206"><designator>3)</designator>
   <para><para.text>content of the list item</para.text></para>
   </list.item>
   </list>
<para updated="20240206"><para.text>This is some para text with a feature following:</para.text></para>
<feature><name>Feature does not move</name>
<para><para.text>Text of the feature</para.text></para></feature>
<para><para.text>This is a para with a nested list following</para.text></para>
<list updated="20240206">
   <heading>
      <name>List 2</name>
   </heading>
   <list.item updated="20240206"><designator>1)</designator>
   <para><para.text>content of the list item</para.text></para>
   </list.item>
   <list.item updated="20240206"><designator>2)</designator>
   <para><para.text>content of the list item</para.text></para>
   <list updated="20240206">
   <heading>
      <name>List 3</name>
   </heading>
   <list.item updated="20240206"><designator>a)</designator>
   <para><para.text>content of the list item</para.text></para>
   </list.item>
   <list.item updated="20240206"><designator>b)</designator>
   <para><para.text>content of the list item</para.text></para>
   </list.item>
   <list.item updated="20240206"><designator>c)</designator>
   <para><para.text>content of the list item</para.text></para>
   </list.item>
   </list>
   </list.item>
   <list.item updated="20240206"><designator>3)</designator>
   <para><para.text>content of the list item</para.text></para>
   <table updated="20240206"><name>This table does not move</name></table>
   </list.item>
   </list>
</section>

输出:

<section>
<para updated="20240206"><para.text>This is some para text.</para.text></para>
<para updated="20240206"><para.text>This is some para text with a list following:</para.text>
<list updated="20240206">
   <heading>
      <name>List 1</name>
   </heading>
   <list.item updated="20240206"><designator>1)</designator>
   <para><para.text>content of the list item</para.text></para>
   </list.item>
   <list.item updated="20240206"><designator>2)</designator>
   <para><para.text>content of the list item</para.text></para>
   </list.item>
   <list.item updated="20240206"><designator>3)</designator>
   <para><para.text>content of the list item</para.text></para>
   </list.item>
   </list>
 </para>
<para updated="20240206"><para.text>This is some para text with a feature following:</para.text></para>
<feature><name>Feature does not move</name>
<para><para.text>Text of the feature</para.text></para></feature>
<para><para.text>This is a para with a nested list following</para.text>
<list updated="20240206">
   <heading>
      <name>List 2</name>
   </heading>
   <list.item updated="20240206"><designator>1)</designator>
   <para><para.text>content of the list item</para.text></para>
   </list.item>
   <list.item updated="20240206"><designator>2)</designator>
   <para><para.text>content of the list item</para.text>
   <list updated="20240206">
   <heading>
      <name>List 3</name>
   </heading>
   <list.item updated="20240206"><designator>a)</designator>
   <para><para.text>content of the list item</para.text></para>
   </list.item>
   <list.item updated="20240206"><designator>b)</designator>
   <para><para.text>content of the list item</para.text></para>
   </list.item>
   <list.item updated="20240206"><designator>c)</designator>
   <para><para.text>content of the list item</para.text></para>
   </list.item>
   </list></para>
   </list.item>
   <list.item updated="20240206"><designator>3)</designator>
   <para><para.text>content of the list item</para.text></para>
   <table updated="20240206"><name>This table does not move</name></table>
   </list.item>
   </list>
   </para>
</section>

尝试了以下操作,但它正在移动该段落之后出现的任何内容。

<!DOCTYPE xsl:stylesheet [<!-- Needed to escape entities to use them in the body of the stylesheet -->
    <!ENTITY sect "&amp;sect;">
]>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" omit-xml-declaration="no"/>
    <!--************************************************************************************-->
    <!--******* Stylesheet to move end para tag after list sibling                **********-->
    <!--************************************************************************************-->
    <xsl:variable name='newline'>
        <xsl:text>
</xsl:text>
    </xsl:variable>
    <!--================================================================-->
    <!--======= Process Root ===========================================-->
    <!--================================================================-->
    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>
    <!--================================================================-->
    <!--======= Process All Content ====================================-->
    <!--================================================================-->
    <xsl:template match="@* | node()">
        <xsl:apply-templates select="@* | node()"/>
    </xsl:template>
    <!--=================================================================-->
    <!--========              Get para and process          =============-->
    <!--=================================================================-->
 <xsl:template match="*[para]">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:for-each-group select="*" group-starting-with="para">
        <xsl:choose>
          <xsl:when test="self::para">
            <xsl:copy>
        <xsl:apply-templates select="@*, node(), subsequence(current-group(), 2)"/>
            </xsl:copy>
          </xsl:when>
          <xsl:otherwise>
            <xsl:apply-templates select="current-group()"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>
    
 <xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

xml xpath xslt
1个回答
0
投票

我认为这可能最好使用兄弟递归来处理。

处理一个节时,对其进行浅复制并处理其第一个子节:

<xsl:template match="section">
  <xsl:copy>
    <xsl:apply-templates select="*[1]" mode="sib"/>
  </xsl:copy>
</xsl:template>

默认情况下,在处理某个部分的子级(包括列表元素)时,处理它并处理其下一个子级:

<xsl:template match="section/*" mode="sib">
  <xsl:apply-templates select="."/>
  <xsl:apply-templates select="following-sibling::*[1]" mode="sib"/>
</xsl:template>

处理para时,在结果元素内部处理以下列表元素,然后在外部处理以下非列表元素:

<xsl:template match="section/para" mode="sib">
  <xsl:copy>
     <xsl:apply-templates/>
     <xsl:apply-templates select="following-sibling::*[1][self::list]"/> mode="sib"/>
  </xsl:copy>
  <xsl:apply-templates select="following-sibling::*[not(self::list)][1]" mode="sib"/>
</xsl:template> 

XSLT 3.0 的完整代码:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all"
  expand-text="yes">

  <xsl:output method="html" indent="no" html-version="5"/>

  <xsl:mode on-no-match="shallow-copy"/>

<xsl:template match="section">
  <xsl:copy>
    <xsl:apply-templates select="*[1]" mode="sib"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="section/*" mode="sib">
  <xsl:apply-templates select="."/>
  <xsl:apply-templates select="following-sibling::*[1]" mode="sib"/>
</xsl:template>

<xsl:template match="section/para" mode="sib">
  <xsl:copy>
     <xsl:apply-templates/>
     <xsl:apply-templates select="following-sibling::*[1][self::list]" mode="sib"/>
  </xsl:copy>
  <xsl:apply-templates select="following-sibling::*[not(self::list)][1]" mode="sib"/>
</xsl:template>  

</xsl:stylesheet> 

对于 2.0(或者实际上 1.0),您必须将 xsl:mode 声明替换为标准身份模板规则。

抱歉,这对于初学者来说是一个相当高级的主题,但仅仅因为您是初学者并不总是意味着您可以从简单的问题开始!

© www.soinside.com 2019 - 2024. All rights reserved.