使用 xsl 3.0 添加新的子元素

Add new child element using xsl 3.0

我需要使用 xsl 3.0 或 xsl 2.0 将 xml 转换为 预期输出 。需要通过组合其 legacyIDcompany.[=16= 为每个 <row> 元素添加名为 <key> </key> 的新元素]

输入XML:

<AggregatedData>
   <Data>
      <Entry>
         <legacyID>ABC</legacyID>
         <AssociateID>123</AssociateID>
      </Entry>
      <Entry>
         <legacyID>CDE</legacyID>
         <AssociateID>456</AssociateID>
      </Entry>
   </Data>
   <root>
      <row>
         <legacyID>ABC</legacyID>
         <company>Test Company 1</company>
         <firstname>Test1</firstname>
      </row>
      <row>
         <legacyID>CDE</legacyID>
         <company>Test Company 2</company>
         <firstname>Test2</firstname>
      </row>
   </root>
</AggregatedData>

预期输出:

<AggregatedData>
   <Data>
      <Entry>
         <legacyID>ABC<legacyID>
         <AssociateID>123<AssociateID>
      <Entry>
      <Entry>
         <legacyID>CDE</legacyID>
         <AssociateID>456</AssociateID>
      </Entry>
   </Data>
   <root>
      <row>
         <key>ABC_Test Company 1</key>
         <legacyID>ABC</legacyID>
         <company>Test Company 1</company>
         <firstname>Test1</firstname>
      </row>
      <row>
         <key>ABC_Test Company 2</key>
         <legacyID>CDE</legacyID>
         <company>Test Company 2</company>
         <firstname>Test2</firstname>
      </row>
   </root>
</AggregatedData>

我使用了下面的 xsl 代码,

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes" />
   <xsl:template match="root/*">
      <xsl:copy>
         <xsl:element name="key">
            <xsl:value-of select="concat(//root/row/legacyID,' ',/row/company)" />
         </xsl:element>
         <xsl:call-template name="copy-children" />
      </xsl:copy>
   </xsl:template>
   <!-- Copy the children of the current node. -->
   <xsl:template name="copy-children">
      <xsl:copy-of select="./*" />
   </xsl:template>
   <!-- Generic identity template -->
   <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="@*" />
         <xsl:apply-templates />
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

但这给出了如下输出,

<?xml version="1.0" encoding="UTF-8"?>
<AggregatedData>
   <Data>
      <Entry>
         <legacyID>ABC</legacyID>
         <AssociateID>123</AssociateID>
      </Entry>
      <Entry>
         <legacyID>CDE</legacyID>
         <AssociateID>456</AssociateID>
      </Entry>
   </Data>
   <root>
      <row>
         <key>ABC_Test Company 1</key>
         <legacyID>ABC</legacyID>
         <company>Test Company 1</company>
         <firstname>Test1</firstname>
      </row>
      <row>
         <key>ABC_Test Company 1</key>
         <legacyID>CDE</legacyID>
         <company>Test Company 2</company>
         <firstname>Test2</firstname>
      </row>
   </root>
</AggregatedData>

根据上面的输出,两行值都使用相同的键值更新。我需要更正它并需要使用 xsl 2.0。

你可以这样做:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="row">
    <xsl:copy>
      <key>
        <xsl:value-of select="concat(legacyID,'_',company)"/>
      </key>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
  
  <!-- Identity transform -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>

看到它在这里工作:https://xsltfiddle.liberty-development.net/

XSLT 3.0 中,您可以将代码缩减为:

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

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

<xsl:template match="row/legacyID">
    <key>{.}_{../company}</key>
    <xsl:copy-of select="."/>
</xsl:template>
  
</xsl:stylesheet>