如果遇到子节点,XSLT关闭xml中的节点

我有以下 XML输入

<?xml version="1.0" encoding="UTF-8"?>
<parent>
    <para>
        <emphasis>
            <emphasis>
                blah 0 
                <Xref ref="1"/>
                blah 1
            </emphasis>
        </emphasis>
    </para>
    <para>
        blah 2 <Xref ref="2"/> blah 3
    </para>
</parent>

我想将Xref节点放置在para节点之外,无论它们有多深。

使用以下 XSLT 1.0 代码:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />

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

    <xsl:key name="kPrecedingXref" match="node()[not(self::Xref)]" use="generate-id(following-sibling::Xref[1])"/>

    <xsl:template match="para[Xref]" priority="1">
        <xsl:apply-templates select="Xref"/>
        <xsl:if test="count(Xref/following-sibling::node())&gt;0">
            <para>
                <xsl:apply-templates select="Xref/following-sibling::node()[not(self::Xref) and not(following-sibling::Xref)]"/>
            </para>
        </xsl:if>
    </xsl:template>

    <xsl:template match="Xref" priority="1">
        <xsl:if test="parent::para">
            <para>
                <xsl:apply-templates select="key('kPrecedingXref',generate-id())"/>
            </para>
        </xsl:if>

        <toolRef><xsl:value-of select="@ref"/></toolRef>
    </xsl:template>

    <xsl:template match="emphasis[Xref]" priority="1">
        <xsl:copy>
                <xsl:apply-templates select="node()[following-sibling::Xref]" />
        </xsl:copy>
        <xsl:apply-templates select="Xref"/>
        <xsl:copy>
                <xsl:apply-templates select="node()[preceding-sibling::Xref]" />
        </xsl:copy>
    </xsl:template>

</xsl:transform>

可以处理此问题,但只能将Xref个节点置于其直接父节点之外。 如何更改此代码以获取此信息:

想要的输出

<parent>
   <para>
      <emphasis>
         <emphasis>
            blah 0 
         </emphasis>
      </emphasis>
   </para>
   <toolRef>1</toolRef>
   <para>
      <emphasis>
         <emphasis>
            blah 1
         </emphasis>
      </emphasis>
   </para>
   <para>blah 2 </para>
   <toolRef>2</toolRef>
   <para> blah 3</para>
</parent>

完整的示例代码为:http://xsltransform.net/nbiCsZM/4

wsntuntun 回答:如果遇到子节点,XSLT关闭xml中的节点

由于michael.hor257k和很多摆弄,我终于找到了解决我的问题的方法。

这是我的有效的XSLT 1.0代码

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" encoding="UTF-8" indent="yes" />

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

    <xsl:template match="@*|node()" priority="0" mode="EXTRACT_XREF">
        <xsl:param name="i" select="0"/>
        <xsl:if test="descendant-or-self::text()[count(preceding-sibling::Xref)=$i]">
            <xsl:copy>
                <xsl:apply-templates select="@*"/>
                <xsl:apply-templates select="node()" mode="EXTRACT_XREF">
                    <xsl:with-param name="i" select="$i"/>
                </xsl:apply-templates>
            </xsl:copy>
        </xsl:if>
    </xsl:template>

    <xsl:template match="para[descendant::Xref]" priority="1">
        <xsl:call-template name="recursive">
            <xsl:with-param name="node" select="."/>
            <xsl:with-param name="count" select="0"/>
            <xsl:with-param name="limit" select="count(descendant::Xref)"/>
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="recursive">
        <xsl:param name="node"/>
        <xsl:param name="count" select="0"/>
        <xsl:param name="limit"/>
        <xsl:if test="$count&lt;=$limit">
            <xsl:apply-templates select="$node" mode="EXTRACT_XREF">
                <xsl:with-param name="i" select="$count"/>
            </xsl:apply-templates>
            <xsl:apply-templates select="$node/descendant::Xref[$count + 1]"/>
            <xsl:call-template name="recursive">
                <xsl:with-param name="node" select="$node"/>
                <xsl:with-param name="count" select="$count + 1"/>
                <xsl:with-param name="limit" select="$limit"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

    <xsl:template match="Xref" priority="1">
        <toolRef>
            <xsl:attribute name="ref">
                <xsl:value-of select="@ref"/>
            </xsl:attribute>
        </toolRef>
    </xsl:template>

</xsl:transform>

我阿拉索添加了一些测试节点,这些节点应该被复制而无需更改,以测试所有可能的情况:

输入XML

<?xml version="1.0" encoding="UTF-8"?>
<parent>
    <dontChangeThisNode></dontChangeThisNode>
    <para>
        <emphasis mode="bold">
            <emphasis mode="underline">blah 0<Xref ref="1"/>blah 1<Xref ref="3"/> blah</emphasis>
        </emphasis>
    </para>
    <dontChangeThisNodeEither>hop</dontChangeThisNodeEither>
    <para>blah 2 <Xref ref="2"/> blah 3</para>
    <para>blah 4</para>
</parent>

最后,这是此代码将其转换为的内容:

XML输出

<?xml version="1.0" encoding="UTF-8"?>
<parent>
   <dontChangeThisNode/>
   <para>
      <emphasis mode="bold">
         <emphasis mode="underline">blah 0</emphasis>
      </emphasis>
   </para>
   <toolRef ref="1"/>
   <para>
      <emphasis mode="bold">
         <emphasis mode="underline">blah 1</emphasis>
      </emphasis>
   </para>
   <toolRef ref="3"/>
   <para>
      <emphasis mode="bold">
         <emphasis mode="underline"> blah</emphasis>
      </emphasis>
   </para>
   <dontChangeThisNodeEither>hop</dontChangeThisNodeEither>
   <para>blah 2 </para>
   <toolRef ref="2"/>
   <para> blah 3</para>
   <para>blah 4</para>
</parent>
本文链接:https://www.f2er.com/3152886.html

大家都在问