将选择节点的兄弟节点移动到新的父节点

时间:2011-03-01 21:45:46

标签: xml xslt

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

<?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>

简单地删除我要包含在注释标记中的段落。我尝试在我链接到的问题中通过样式表逐行进行...任何想法? 谢谢, bp的

2 个答案:

答案 0 :(得分:3)

这是对para元素进行分组。

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

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

<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>

答案 1 :(得分:1)

我会这样做

<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. 具有先前兄弟section的{​​{1}}的覆盖模板将所有此类兄弟包裹在para元素中,然后自行调用身份转换。

  3. 为方便起见,我们定义了一个键,该键匹配comment元素前面的所有para元素与给定的section

  4. 具有以下兄弟generate-id()的{​​{1}}元素将通过覆盖模板排除在身份规则的操作之外,该模板根本不执行任何操作。

  5. 最后,在包装器para中输出时,此类section元素在模式para中处理,模式comment只调用标识规则进行复制。