当前位置: 首页 > 知识库问答 >
问题:

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

酆景辉
2023-03-14
        <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>
    <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>
        <?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>

第一个代码学院已经被解析,B1节点被设置在B节点之后,节点C、D和E之前,或者换句话说,B1节点被设置,必须位于它之后的节点是:C、D和E。
第二个模板match=“root/E/other/deal/keys”应该满足第二个挑战部分:将第二个关键节点添加到/root/E/other/deal/keys结构中,已经被完全忽略。除此之外,如果在根节点上注释第一个模板匹配,第二个模板match=“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>

共有1个答案

西门飞翮
2023-03-14

第二个模板match=“root/e/othe/deal/keys”应该满足第二个挑战部分:将第二个关键节点添加/root/e/othe/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>

在提供的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>

产生了想要的、正确的结果:

<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>
 类似资料:
  • 问题内容: Helm允许在Kubernetes的资源文件中使用Go模板。 通常使用一个名为的文件通过以下语法定义Go模板助手: 然后可以在资源文件中使用它,如下所示: 问题 如何在其他帮助程序定义中使用定义的帮助程序? 例如,如果我有一个用于应用程序名称的助手,并想在定义入口主机名的助手的定义中使用该助手,该怎么办? 我尝试了几种其他方式来调用其他定义中的帮助器。鉴于此基本辅助功能: 我尝试了以下

  • 在 cmf中模板就是一个 html 文件,可分为前台模板文件和后台模板文件; 前台模板位于 themes 目录下,后台模板位于 admin/themes 目录下,前后台都是多主题机制的,可以分开设置不同的主题; 前台默认模板是 simplebootx,以后也可能会换,我们先以这个为例; 这是前台模板的结构;应用之间彼此分开,Portal目录下就对应的是application/Portal应用的模板

  • 问题内容: 这是我的自定义过滤器: 这是我尝试在模板文件中使用它导致错误的方式: | 我查看了django的文档和书籍,但只发现了使用单个参数的示例……甚至可能吗? 问题答案: 这是可能的并且相当简单。 Django只允许在过滤器中使用一个参数,但是没有理由不能使用逗号将所有参数都放在一个字符串中。 因此,例如,如果你需要一个过滤器来检查变量X是否在列表[1,2,3,4]中,则需要一个如下所示的模

  • 从MinDoc v0.13及以上版本开始支持自定义模板(仅Markdown编辑器)。 创建自定义模板 用户可在编辑项目时将编辑器内的内容报错为模板: 点击保存按钮右侧的公文包按钮会弹出保存为模板的界面: 填写模板名称点击立即保存即可。 全局模板是指,在其他项目中可用,目前仅支持管理员保存全局模板,非管理员及时选中了全局,保存时也是仅项目内可用。 使用自定义模板 点击编辑器上的模板按钮可以显示选择模

  • 我试图用成员模板函数实现一个可变类模板,其模板参数独立于类模板参数,但在定义成员模板时遇到了问题。 我将问题简化为尝试编译此文件(抱歉,无法进一步简化): 在尝试编译(C 11)时,我遇到以下错误: 我很确定它归结为第一个和第五个错误,但不知道我做错了什么。为什么

  • 以下模板部署: https://gist.github.com/rnkhouse/aea0a8fd395da37b19466348b919d620 错误: “部署失败,状态代码为400,消息:部署模板验证失败:'模板中未定义资源'Microsoft.Network/virtualNetworks/mtes dev VNET'。请参阅。”https://aka.ms/arm-template有关用法