【问题标题】:Move certain nodes that are sibling of select node into a new parent node将某些与选择节点同级的节点移动到新的父节点中
【发布时间】:2011-03-01 21:45:46
【问题描述】:

我在这里进行了一些搜索,发现了一些与我的问题相关的问题,但我仍然遇到问题......(希望我可以添加一个新问题而不是评论现有问题...... )

<?xml version="1.0"?>
<section>
    <title>Main Section</title>
    <para>Here is some text that is a child of a main section.</para>
    <para>Some more text.</para>
    <para>When a section has subsections, it should not have loose paragraphs before the first sub section. Those loose paras should be placed inside a comment element.</para>
    <section>
        <title>This is my subsection</title>
        <para>Text that is inside of the sub-section</para>
        <para>And some more sub section text.</para>
    </section>
</section>

我想将 /section/para 放置在新创建的评论节点中,如下所示:

<?xml version="1.0"?>
<section>
    <title>Main Section</title>
    <comment>
       <para>Here is some text that is a child of a main section.</para>
       <para>Some more text.</para>
       <para>When a section has subsections, it should not have loose paragraphs before the first sub section. Those loose paras should be placed inside a comment element.</para>
    </comment>
    <section>
        <title>This is my subsection</title>
        <para>Text that is inside of the sub-section</para>
        <para>And some more sub section text.</para>
    </section>
</section>

我尝试了一些在stackoverflow中找到的建议,最接近的是here.

这是我正在使用的样式表:

<?xml version='1.0'?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>


<xsl:template match="node()|@*" name="identity">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>


<!-- paras that are children of a section that has direct para children and dircect section children -->
<xsl:template match="section[para][section]/para[1]">
    <comment>
        <xsl:apply-templates select="../para" mode="commentPara"/>

    </comment>
</xsl:template>

<xsl:template match="*" mode="commentPara">
    <xsl:call-template name="identity"/>
</xsl:template>

<xsl:template match="section[para][section]/para"/>


</xsl:stylesheet>

它正在输出这个:

<?xml version='1.0' ?>
<section>
    <title>Main Section</title>



    <section>
        <title>This is my subsection</title>
        <para>Text that is inside of the sub-section</para>
        <para>And some more sub section text.</para>
    </section>
</section>

只需删除我想要包含在评论标签中的 paras。我尝试在我链接到的问题中逐行浏览样式表......有什么想法吗? 谢谢, bp

【问题讨论】:

  • 亲爱的坏人,这是个好问题,+1。请参阅我的答案以获得完整、简单、简短且容易的解决方案,该解决方案也可能比其他解决方案更有效,而不是使用密钥。 :)

标签: xml xslt


【解决方案1】:

这是对相邻的 para 元素进行分组。

问题出在Conflict Resolution for Template Rules:因为两个para匹配规则具有相同的导入优先级和相同的计算优先级,错误恢复机制可能导致应用最后一个。

您需要在“第一个para 子”规则上明确定义@priority,例如:

<xsl:template match="section[para][section]/para[1]" priority="1">
</

经过这样的修改,输出为:

<?xml version="1.0" encoding="UTF-16"?>
<section>
    <title>Main Section</title>
    <comment>
        <para>Here is some text that is a child of a main section.</para>
        <para>Some more text.</para>
        <para>When a section has subsections, it should not have loose paragraphs before the first sub section. Those loose paras should be placed inside a comment element.</para>
    </comment>
    <section>
        <title>This is my subsection</title>
        <para>Text that is inside of the sub-section</para>
        <para>And some more sub section text.</para>
    </section>
</section>

【讨论】:

    【解决方案2】:

    我会这样做

    <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:key name="kPreceding" match="para"
      use="generate-id(following-sibling::section[1])"/>
    
     <xsl:template match="node()|@*" name="identity">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match="section[preceding-sibling::para]">
      <comment>
       <xsl:apply-templates mode="copy"
            select="key('kPreceding', generate-id())"/>
      </comment>
    
      <xsl:call-template name="identity"/>
     </xsl:template>
    
     <xsl:template match=
      "para[following-sibling::section]"/>
    
     <xsl:template match="para" mode="copy">
      <xsl:call-template name="identity"/>
     </xsl:template>
    </xsl:stylesheet>
    

    当此转换应用于提供的 XML 文档时:

    <section>
        <title>Main Section</title>
        <para>Here is some text that is a child of a main section.</para>
        <para>Some more text.</para>
        <para>When a section has subsections, it should not have loose paragraphs before the first sub section. Those loose paras should be placed inside a comment element.</para>
        <section>
            <title>This is my subsection</title>
            <para>Text that is inside of the sub-section</para>
            <para>And some more sub section text.</para>
        </section>
    </section>
    

    产生了想要的正确结果:

    <section>
       <title>Main Section</title>
       <comment>
          <para>Here is some text that is a child of a main section.</para>
          <para>Some more text.</para>
          <para>When a section has subsections, it should not have loose paragraphs before the first sub section. Those loose paras should be placed inside a comment element.</para>
       </comment>
       <section>
          <title>This is my subsection</title>
          <para>Text that is inside of the sub-section</para>
          <para>And some more sub section text.</para>
       </section>
    </section>
    

    解释

    1. 身份规则(模板)“按原样”复制每个节点。

    2. 具有前面兄弟parasection 的覆盖模板使用comment 元素包装所有此类兄弟,然后对其自身调用身份转换。

    3. 为方便起见,我们定义了一个键,将section 元素之前的所有para 元素与给定的generate-id() 匹配。

    4. 具有以下兄弟sectionpara 元素被覆盖模板从身份规则的操作中排除,这根本不做任何事情。

    5. 1234563

    【讨论】:

      猜你喜欢
      • 2013-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-31
      相关资源
      最近更新 更多