Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml 如何使用XSL复制节点并更改其(原始和重复)嵌套子节点的值?_Xml_Xslt - Fatal编程技术网

Xml 如何使用XSL复制节点并更改其(原始和重复)嵌套子节点的值?

Xml 如何使用XSL复制节点并更改其(原始和重复)嵌套子节点的值?,xml,xslt,Xml,Xslt,我刚刚开始使用XSL,需要有经验的人的帮助 我有一个包含大量内容的XML中的节点a。我想复制这个节点,通过其中嵌套标记的值来标识它 在创建与节点A相同的节点A'后,我想更改标识节点A的标记的值:节点A和节点A'。两个节点的新值将不同 以下是我的源XML: <businessFields> <businessField> <businessFieldID> <namespace>

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

我有一个包含大量内容的XML中的节点a。我想复制这个节点,通过其中嵌套标记的值来标识它

在创建与节点A相同的节点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>

福
福巴
java.lang.Boolean
错误的
酒吧
foobar3
java.lang.String
不
我需要在/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>

福
foobar1
java.lang.Boolean
错误的
福
foobar2
java.lang.Boolean
错误的
酒吧
foobar3
java.lang.String
不
我尝试使用
迭代所有以foobar作为值的节点,并根据
位置()更改值,但我弄错了一些东西,它只是将所有节点的名称更改为相同的名称

这是我关于stackoverflow的第一个问题,英语不是我的母语,如果不清楚,很抱歉。请让我知道我能做些什么来改进我的问题,并感谢您的帮助。

如果我理解正确(这一点不确定),您想做:

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

foobar1
foobar2

2021年的撒克逊对我来说听起来像XSLT 3,所以也许

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">
    
  <xsl:param name="name-to-check" as="xs:string">foobar</xsl:param>
  
  <xsl:param name="new-value" as="xs:string">foobar</xsl:param>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="businessField[businessFieldID/name = $name-to-check]">
      <xsl:copy>
          <xsl:apply-templates>
              <xsl:with-param name="suffix" tunnel="yes" select="1"/>
          </xsl:apply-templates>
      </xsl:copy>
      <xsl:copy>
          <xsl:apply-templates>
              <xsl:with-param name="suffix" tunnel="yes" select="2"/>
          </xsl:apply-templates>
      </xsl:copy>
  </xsl:template>
  
  <xsl:template match="businessField/businessFieldID/name[. = $name-to-check]/text()">
      <xsl:param name="suffix" tunnel="yes"/>
      <xsl:value-of select="$new-value || $suffix"/>
  </xsl:template>
  
</xsl:stylesheet>

福巴
福巴
够了,甚至

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">
    
  <xsl:param name="name-to-check" as="xs:string">foobar</xsl:param>
  
  <xsl:param name="new-value" as="xs:string">foobar</xsl:param>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="businessField[businessFieldID/name = $name-to-check]">
      <xsl:apply-templates select="., ." mode="change"/>
  </xsl:template>
  
  <xsl:template match="businessField" mode="change">
      <xsl:copy>
          <xsl:apply-templates mode="#default">
              <xsl:with-param name="suffix" tunnel="yes" select="position()"/>
          </xsl:apply-templates>
      </xsl:copy>
  </xsl:template>
  
  <xsl:template match="businessField/businessFieldID/name[. = $name-to-check]/text()">
      <xsl:param name="suffix" tunnel="yes"/>
      <xsl:value-of select="$new-value || $suffix"/>
  </xsl:template>
  
</xsl:stylesheet>

福巴
福巴

您使用哪个版本的XSLT,哪个XSLT处理器?制作
businessField[businessFieldID/name='foobar']
的深度副本,并将其推送到模板中,或者在与
businessField[businessFieldID/name='foobar']
@MartinHonnen匹配的模板中使用
两次,因为它是1.0版和萨克森处理器。至于你的建议,我想我已经在做你刚才描述的事情了。除非我遗漏了什么。@PawełRuta您是在Saxon中使用XSLT1.0吗?为什么?它工作得很好
mode=“duplicate”
是我丢失的部分。谢谢你,伙计!