如何应用多个模板定义,其中每个模板定义都在更改相同的XML结构

Har*_*ica 6 xml xslt

在这个代码示例中,我有两个挑战,一个是在B节点之后和节点C,D和E之前设置B1节点,第二个挑战是将第二个KEY节点添加到/ ROOT/E/OTHER/DEAL/KEYS结构.

这个XML示例:

        <ROOT>
          <A>some A text</A>
          <B>some B text</B>
          <C>some C text</C>
          <D>some D text</D>
          <E>
            <OTHER>
              <DEAL>
                <KEYS>
                  <KEY>
                    <KeyIdentifierType>KeyIdentifierTypeA</KeyIdentifierType>
                    <KeyValue>123456|1</KeyValue>
                  </KEY>
                </KEYS>
              </DEAL>
            </OTHER>
          </E>
        </ROOT>
Run Code Online (Sandbox Code Playgroud)

改造后:

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <xsl:strip-space elements="*"/>
        <xsl:output method="xml" indent="yes"/>

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

        <!-- Identifiers are added by the system. Need to pass parms from the calling program -->
        <xsl:template match="ROOT" name="add-B1">
            <xsl:variable name="elements-after" select="C|D|E"/>
            <xsl:copy>
                <xsl:copy-of select="* except $elements-after"/>
                <B1>some B1 text</B1>
                <xsl:copy-of select="$elements-after"/>
            </xsl:copy>
        </xsl:template>

        <!-- KEY is added by the system. Need to pass parms from the calling program -->
        <xsl:template match="ROOT/E/OTHER/DEAL/KEYS" name="add-KEYS">
            <xsl:param name="KeyIdentifierTypeB">654321|1</xsl:param>
            <xsl:copy>
                <xsl:copy-of select="*"/>
                <KEY>
                    <KeyIdentifierType>KeyIdentifierTypeB</KeyIdentifierType>
                    <KeyValue>
                        <xsl:value-of select="$KeyIdentifierTypeB"/>
                    </KeyValue>
                </KEY>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

成为:

        <?xml version="1.0" encoding="UTF-8"?>
        <ROOT>
            <A>some A text</A>
            <B>some B text</B>
            <B1 xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">some B1 text</B1>
            <C>some C text</C>
            <D>some D text</D>
            <E>
                <OTHER>
                    <DEAL>
                        <KEYS>
                            <KEY>
                                <KeyIdentifierType>KeyIdentifierTypeA</KeyIdentifierType>
                                <KeyValue>123456|1</KeyValue>
                            </KEY>
                        </KEYS>
                    </DEAL>
                </OTHER>
            </E>
        </ROOT>
Run Code Online (Sandbox Code Playgroud)

为什么第二个模板定义被完全忽略了?

第一个代码学院已解决B1节点在B节点之后和节点C,D和E之前设置或者换句话说B1节点被设置,并且必须在其之后的节点是:C,D和E.
第二个模板match ="ROOT/E/OTHER/DEAL/KEYS"应该满足第二个挑战部分:将第二个KEY节点添加到/ ROOT/E/OTHER/DEAL/KEYS结构,已被完全忽略.除了这个事实,如果你在ROOT节点上评论第一个模板匹配,第二个模板匹配="ROOT/E/OTHER/DEAL/KEYS"将正常工作,它实际上会添加额外的密钥,但我不知道我知道为什么第一个模板匹配总是覆盖第二个模板匹配.我尝试xsl:template match ="ROOT/E/OTHER/DEAL/KEYS ...和xsl:for-each select = ...和xsl:call-template name ="add-KEYS"但没有任何帮助我出.

我实际上理解,apply-templates,匹配具有更高优先级结构的节点模板.更改XSLT文件中的模板位置不会产生任何影响,它不会按照确切的行序列读取它,而是通过匹配优先级来处理它.每个匹配模板的"apply-templates"将对XML结构进行更改,隐式地它将为我们制作"for-each",但我不知道如何"建议"结构已更改的第二个模板,以及为什么我应该这样做,因为第二个模板匹配正在寻找不同的XPath位置,从来没有从第一个模板触及btw.我应该在我的案例中应用模板排序吗?...以及如何做到这一点的最佳做法是什么?

预期结果:

        <?xml version="1.0" encoding="UTF-8"?>
        <ROOT>
            <A>some A text</A>
            <B>some B text</B>
            <B1>some B1 text</B1>
            <C>some C text</C>
            <D>some D text</D>
            <E>
                <OTHER>
                    <DEAL>
                        <KEYS>
                            <KEY>
                                <KeyIdentifierType>KeyIdentifierTypeA</KeyIdentifierType>
                                <KeyValue>123456|1</KeyValue>
                            </KEY>
                            <KEY>
                                <KeyIdentifierType>KeyIdentifierTypeB</KeyIdentifierType>
                                <KeyValue>654321|1</KeyValue>
                            </KEY>
                        </KEYS>
                    </DEAL>
                </OTHER>
            </E>
        </ROOT>
Run Code Online (Sandbox Code Playgroud)

Dim*_*hev 3

应该满足第二个挑战部分的第二个模板match="ROOT/E/OTHER/DEAL/KEYS":将第二个 KEY 节点添加到结构中 /ROOT/E/OTHER/DEAL/KEYS,已被完全忽略。

问题是模板匹配中ROOT没有任何xsl:apply-templates. 模板仅根据xsl:apply-templates指令的结果被选择执行。在您的代码中没有任何xsl:apply-templates,因此 XSLT 处理器不再应用模板并完成执行。

xsl:copy-of如果换成的话,情况就不一样了xsl:apply-templates

以下是如何执行此操作

<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:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="/*">
  <xsl:copy>
    <xsl:apply-templates select="@*|B/preceding-sibling::node()"/>
    <xsl:apply-templates select="B"/>
    <B1>some B1 text</B1>
    <xsl:apply-templates select="B/following-sibling::node()"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="KEY">
  <xsl:copy>
   <xsl:apply-templates select="@*|node()"/>
   <KEY>
    <KeyIdentifierType>KeyIdentifierTypeB</KeyIdentifierType>
    <KeyValue>
     <xsl:value-of select="'654321|1'"/>
    </KeyValue>
   </KEY>
   </xsl:copy>
 </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

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

<ROOT>
    <A>some A text</A>
    <B>some B text</B>
    <C>some C text</C>
    <D>some D text</D>
    <E>
        <OTHER>
            <DEAL>
                <KEYS>
                    <KEY>
                        <KeyIdentifierType>KeyIdentifierTypeA</KeyIdentifierType>
                        <KeyValue>123456|1</KeyValue>
                    </KEY>
                </KEYS>
            </DEAL>
        </OTHER>
    </E>
</ROOT>
Run Code Online (Sandbox Code Playgroud)

产生了想要的正确结果

<ROOT>
   <A>some A text</A>
   <B>some B text</B>
   <B1>some B1 text</B1>
   <C>some C text</C>
   <D>some D text</D>
   <E>
      <OTHER>
         <DEAL>
            <KEYS>
               <KEY>
                  <KeyIdentifierType>KeyIdentifierTypeA</KeyIdentifierType>
                  <KeyValue>123456|1</KeyValue>
                  <KEY>
                     <KeyIdentifierType>KeyIdentifierTypeB</KeyIdentifierType>
                     <KeyValue>654321|1</KeyValue>
                  </KEY>
               </KEY>
            </KEYS>
         </DEAL>
      </OTHER>
   </E>
</ROOT>
Run Code Online (Sandbox Code Playgroud)