XSLT:通过复制外部文件中具有属性值的标签来转换 xml 文件

XSLT : Transform xml file by duplicating tags having attribute value in external file

我有两个文件;

items.xml : 要转换的文件

<items>
  <item cat="cat_id1">
     <link>link1</link>
     <link>link11</link>
  </item>
  <item cat="cat_id2">
     <link>link2</link>
     <link>link22</link>
  </item>
  <item cat="cat_id3">
     <link>link3</link>
  </item>
</items> 

items_to_transforme.xml :包含要翻译的类别的标识符

<categories>
<categorie>cat_id1</categorie>
<categorie>cat_id3</categorie>
</categories>

我需要通过复制文件 items_to_transforme.xml 中具有 cat 属性值的标签来转换 items.xml,然后更改属性值

想要的结果:

<items>
  <item cat="cat_id1">
     <link>link1</link>
     <link>link11</link>
  </item>
  <item cat="cat_id1-FR">
     <link>link1</link>
     <link>link11</link>
  </item>
  <item cat="cat_id2">
     <link>link2</link>
     <link>link22</link>
  </item>
  <item cat="cat_id3">
     <link>link3</link>
  </item>
  <item cat="cat_id3-FR">
     <link>link3</link>
  </item>
</items>  

我如何使用 xslt 执行此操作?我是 xslt 的新手,感谢您的帮助。

为第二个文档中的元素定义一个键,并将其用于您复制匹配元素的模板的匹配模式(例如,通过将处理委托给身份转换设置):

<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="categories-doc">
<categories>
<categorie>cat_id1</categorie>
<categorie>cat_id3</categorie>
</categories>      
  </xsl:param>

  <xsl:key name="cat-key" match="categorie" use="."/>

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

  <xsl:template match="item[key('cat-key', @cat, $categories-doc)]">
      <xsl:next-match/>
      <xsl:apply-templates select="." mode="change-id"/>
  </xsl:template>

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

  <xsl:template mode="change-id" match="item/@cat">
      <xsl:attribute name="{name()}" select=". || '-FR'"/>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/gWEamLh/1 内联了第二个文档以确保示例的完整性,但当然可以使用 <xsl:param name="categories-doc" select="doc('categories.xml')"/>。示例还使用 XSLT 3,身份转换是使用 xsl:mode 声明设置的,但当然对于 XSLT 2,您可以将其拼写为模板。

XSLT 1.0 解决方案:

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

  <xsl:template match=
  "item[@cat = document('file:///c:/temp/DeleteMe/items-to-transform.xml')/*/categorie]">
    <xsl:call-template name="identity"/>
    <item cat="{@cat}-FR">
      <xsl:apply-templates/>
    </item>
  </xsl:template>
</xsl:stylesheet>

当此转换应用于第一个 XML 文档时:

<items>
  <item cat="cat_id1">
     <link>link1</link>
     <link>link11</link>
  </item>
  <item cat="cat_id2">
     <link>link2</link>
     <link>link22</link>
  </item>
  <item cat="cat_id3">
     <link>link3</link>
  </item>
</items>

第二个文档位于 C:\tem[\DeleteMe\items-to-transform.xml 的文件中,拼写错误已更正,因此这是一个格式正确的 XML 文档:

<categories>
    <categorie>cat_id1</categorie>
    <categorie>cat_id3</categorie>
</categories>

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

<items>
   <item cat="cat_id1">
      <link>link1</link>
      <link>link11</link>
   </item>
   <item cat="cat_id1-FR">
      <link>link1</link>
      <link>link11</link>
   </item>
   <item cat="cat_id2">
      <link>link2</link>
      <link>link22</link>
   </item>
   <item cat="cat_id3">
      <link>link3</link>
   </item>
   <item cat="cat_id3-FR">
      <link>link3</link>
   </item>
</items>