首页 > 解决方案 > 如何使用 XSL 复制节点并更改其(原始和重复的)嵌套子节点的值?

问题描述

我刚开始使用 XSL,我需要有经验的人的帮助。

我在一个包含很多内容的 XML 中有一个节点 A。我想复制这个节点,通过它里面的嵌套标签的值来识别它。

创建与节点 AI 相同的节点 A' 后,想要更改我为节点 A 标识的标签的值:节点 A 和节点 A'。两个节点的新值将不同。

这是我的源 XML:

<businessFields>
      <businessField>
            <businessFieldID>
               <namespace>
                  <name>foo</name>
               </namespace>
               <name>foobar</name>
            </businessFieldID>
            <datatype>java.lang.Boolean</datatype>
            <value>false</value>
      </businessField>
      <businessField>
         <businessFieldID>
            <namespace>
               <name>bar</name>
            </namespace>
            <name>foobar3</name>
         </businessFieldID>
         <datatype>java.lang.String</datatype>
         <value>No</value>
      </businessField>

    <!-- some more businessField nodes-->
</businessFields>

我需要在/businessFields/businessField/businessFieldID/name标记中复制具有foobar值的节点,并且我想为两个节点更改此值。

我的 XSL 看起来像这样:

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

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

   <xsl:template match="//businessField[businessFieldID/name='foobar']">
        <xsl:copy-of select="."/>
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
   </xsl:template>
   
   
    <xsl:template match="//businessField[businessFieldID/name='foobar']/businessFieldID/name/text()">
        <xsl:value-of select="'foobar1'"/>
    </xsl:template>
  
</xsl:stylesheet>

所以基本上我能够复制我感兴趣的节点并更改所需名称标签的值,但仅限于其中一个节点。

这是所需的输出:

<?xml version="1.0" encoding="UTF-8"?>
<businessFields>
      <businessField>
            <businessFieldID>
               <namespace>
                  <name>foo</name>
               </namespace>
               <name>foobar1</name>
            </businessFieldID>
            <datatype>java.lang.Boolean</datatype>
            <value>false</value>
      </businessField>
   <businessField>
            <businessFieldID>
               <namespace>
                  <name>foo</name>
               </namespace>
               <name>foobar2</name>
            </businessFieldID>
            <datatype>java.lang.Boolean</datatype>
            <value>false</value>
      </businessField>
      <businessField>
         <businessFieldID>
            <namespace>
               <name>bar</name>
            </namespace>
            <name>foobar3</name>
         </businessFieldID>
         <datatype>java.lang.String</datatype>
         <value>No</value>
      </businessField>
</businessFields>

我尝试使用<xsl:for-each>迭代所有以foobar作为值的节点并根据值更改值,position()但我搞砸了一些东西,它只是将它更改为所有节点的相同名称。

这是我关于 stackoverflow 的第一个问题,英语不是我的母语,如果不清楚,请见谅。请让我知道我该怎么做才能使我的问题变得更好,并感谢您的帮助。

标签: xmlxslt

解决方案


如果我理解正确(这完全不确定),你想做:

XSLT 1.0

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

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

<xsl:template match="businessField[businessFieldID/name='foobar']">
    <!-- original -->
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
    <!-- duplicate -->
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" mode="duplicate"/>
    </xsl:copy>
</xsl:template>

<!-- identity transform for duplicates -->
<xsl:template match="@*|node()" mode="duplicate">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" mode="duplicate"/>
    </xsl:copy>
</xsl:template>
     
<!-- modify original -->
<xsl:template match="businessField[businessFieldID/name='foobar']/businessFieldID/name/text()">
    <xsl:text>foobar1</xsl:text>
</xsl:template>

<!-- modify duplicate -->
<xsl:template match="businessField[businessFieldID/name='foobar']/businessFieldID/name/text()" mode="duplicate">
    <xsl:text>foobar2</xsl:text>
</xsl:template>
  
</xsl:stylesheet>

推荐阅读