xslt调用模板与动态匹配

ati*_*tif 6 xslt xslt-2.0 xslt-1.0

我试图调用动态参数,同时调用模板来抑制xml中的节点.

我会称这个模板为:

transform employee.xml suppress.xsl ElementsToSuppress=id,fname 
Run Code Online (Sandbox Code Playgroud)

employee.xml

<?xml version="1.0" encoding="utf-8" ?>
<Employees>
  <Employee>
    <id>1</id>
    <firstname>xyz</firstname>
    <lastname>abc</lastname>
    <age>32</age>
    <department>xyz</department>
  </Employee>
  <Employee>
    <id>2</id>
    <firstname>XY</firstname>
    <lastname>Z</lastname>
    <age>21</age>
    <department>xyz</department>
  </Employee>
</Employees>
Run Code Online (Sandbox Code Playgroud)

Suppress.xsl

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

  <elements:name abbrev="id">id</elements:name>
  <elements:name abbrev="fname">firstname</elements:name>

  <xsl:param name="ElementsToSuppress" ></xsl:param>

  <xsl:variable name="tokenizedSample" select="tokenize($ElementsToSuppress,',')"/>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
    <xsl:for-each select="$tokenizedSample">
      <xsl:call-template name ="Suppress"  >
        <xsl:with-param  name="parElementName">
          <xsl:value-of select="."/>
        </xsl:with-param>
      </xsl:call-template>
    </xsl:for-each>

  </xsl:template>






  <xsl:template name="Suppress">
    <xsl:param name="parElementName" select="''"></xsl:param>
    <xsl:variable name="extNode" select="document('')/*/elements:name[@abbrev=$parElementName]"/>
    <xsl:call-template name="test" >
      <xsl:with-param name="parElementName" >
        <xsl:value-of select="$extNode"/>
      </xsl:with-param>
    </xsl:call-template>
  </xsl:template>


  <xsl:template name="test"  match="*[name() = $parElementName]" >
    <xsl:param name="parElementName" select="''"></xsl:param>
    <xsl:call-template name="SuppressElement" />    
  </xsl:template>

  <xsl:template name="SuppressElement" />

</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

我们可以通过这种或其他方式实现输出吗?理想的方法是传递节点的逗号分隔缩写并在一次调用中抑制它们.

任何帮助将不胜感激.

问候,

AB

Dim*_*hev 7

您不需要XSLT 2.0进行此处理.

这个XSLT 1.0转换:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:param name="pNodesToSuppress"
      select="'id,fname,pi'"/>

  <my:toSuppress>
   <name abbrev="id">id</name>
   <name abbrev="fname">firstname</name>
   <name abbrev="pi">somePI</name>
  </my:toSuppress>

 <xsl:variable name="vToSuppressTable" select=
  "document('')/*/my:toSuppress/*"/>

 <xsl:variable name="vNamesToSupress">
  <xsl:for-each select=
   "$vToSuppressTable
     [contains(concat(',',$pNodesToSuppress,','),
               concat(',',@abbrev, ',')
               )
     ]">
   <xsl:value-of select="concat(',',.)"/>
   </xsl:for-each>
   <xsl:text>,</xsl:text>
 </xsl:variable>

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

 <xsl:template match="node()" priority="0.01">
  <xsl:if test=
     "not(contains($vNamesToSupress,
                   concat(',',name(),',')
                   )
          )">
   <xsl:call-template name="identity"/>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

当应用于提供的XML文档时(添加了处理指令以演示我们如何删除PI - 不仅仅是元素):

<Employees>
  <Employee>
    <id>1</id>
    <firstname>xyz</firstname>
    <lastname>abc</lastname>
    <age>32</age>
    <department>xyz</department>
  </Employee>
  <?somePI This PI will be deleted ?>
  <Employee>
    <id>2</id>
    <firstname>XY</firstname>
    <lastname>Z</lastname>
    <age>21</age>
    <department>xyz</department>
  </Employee>
</Employees>
Run Code Online (Sandbox Code Playgroud)

产生想要的,正确的结果:

<Employees>
   <Employee>
      <lastname>abc</lastname>
      <age>32</age>
      <department>xyz</department>
   </Employee>
   <Employee>
      <lastname>Z</lastname>
      <age>21</age>
      <department>xyz</department>
   </Employee>
</Employees>
Run Code Online (Sandbox Code Playgroud)

请注意:

  1. 这是纯XSLT 1.0转换.

    2. 当通过外部参数指定其名称时,不仅会删除元素,还会删除处理指令$pNodesToSuppress.


Mar*_*nen 4

我不明白为什么参数值“fname”会抑制名为“firstname”的元素,但除此之外,您可能只是想要

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs"
  version="2.0">

  <xsl:param name="ElementsToSuppress" as="xs:string" select="'id,firstname'"/>
  <xsl:variable name="names-to-suppress" as="xs:QName*"
    select="for $s in tokenize($ElementsToSuppress, ',') return QName('', $s)"/>

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

  <xsl:template match="*[node-name(.) = $names-to-suppress]"/>

</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

[编辑] 我错过了您的示例样式表似乎包含从这些参数到示例输入中的元素名称的映射。在这种情况下,这里是样式表的改编版本来处理这种情况:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:data="http://example.com/data"
  xmlns:elements="http://example.com/elements"
  exclude-result-prefixes="xs data elements"
  version="2.0">

  <data:data>
    <elements:name abbrev="id">id</elements:name>
    <elements:name abbrev="fname">firstname</elements:name>
  </data:data>

  <xsl:key name="e-by-abbrev" match="elements:name" use="@abbrev"/>

  <xsl:param name="ElementsToSuppress" as="xs:string" select="'id,fname'"/>
  <xsl:variable name="names-to-suppress" as="xs:QName*"
    select="for $s in tokenize($ElementsToSuppress, ',') return QName('', key('e-by-abbrev', $s, document('')/xsl:stylesheet/data:data))"/>

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

  <xsl:template match="*[node-name(.) = $names-to-suppress]"/>

</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

[第二次编辑以实现进一步的请求] 这是一个还检查属性值的示例relationship

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:data="http://example.com/data"
  xmlns:elements="http://example.com/elements"
  exclude-result-prefixes="xs data elements"
  version="2.0">

  <xsl:param name="ElementsToSuppress" as="xs:string" select="'id'"/>

  <xsl:param name="parVAObjectRelationship" as="xs:string" select="'a,b'"/>

  <xsl:variable name="names-to-suppress" as="xs:QName*"
    select="for $s in tokenize($ElementsToSuppress, ',') return QName('', key('e-by-abbrev', $s, document('')/xsl:stylesheet/data:data))"/>

  <xsl:variable name="att-values-to-suppress" as="xs:string*"
    select="tokenize($parVAObjectRelationship, ',')"/>

  <data:data>
    <elements:name abbrev="id">id</elements:name>
    <elements:name abbrev="fname">firstname</elements:name>
  </data:data>

  <xsl:key name="e-by-abbrev" match="elements:name" use="@abbrev"/>

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

  <xsl:template match="*[@relationship = $att-values-to-suppress]"/>

  <xsl:template match="*[node-name(.) = $names-to-suppress]"/>

</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

当应用于

<Employees>
  <Employee>
    <id>1</id>
    <firstname>xyz</firstname>
    <lastname relationship="a">abc</lastname>
    <age relationship="b">32</age>
    <department>xyz</department>
  </Employee>
</Employees>
Run Code Online (Sandbox Code Playgroud)

输出是

<Employees>
  <Employee>

    <firstname>xyz</firstname>


    <department>xyz</department>
  </Employee>
</Employees>
Run Code Online (Sandbox Code Playgroud)

您可能需要添加 strip-space 并输出 indent="yes" 以防止出现空行。