使用XSLT添加强制节点

问题描述:

我面临着xslt/xpath问题,希望有人能够帮到忙,用几句话来说,这是我尝试实现的目标。使用XSLT添加强制节点

我必须转换XML文档,其中可能缺少一些节点,这些缺失节点在最终结果中是强制性的。我在xsl:param中提供了一组强制节点名称。

的基本文档是:

<?xml version="1.0"?> 
<?xml-stylesheet type="text/xsl" href="TRANSFORM.xslt"?> 
<BEGIN> 
    <CLIENT> 
     <NUMBER>0021732561</NUMBER> 
     <NAME1>John</NAME1> 
     <NAME2>Connor</NAME2> 
    </CLIENT> 

    <PRODUCTS> 
     <PRODUCT_ID>12</PRODUCT_ID> 
      <DESCRIPTION>blah blah</DESCRIPTION> 
    </PRODUCTS> 

    <PRODUCTS> 
     <PRODUCT_ID>13</PRODUCT_ID> 
      <DESCRIPTION>description ...</DESCRIPTION> 
    </PRODUCTS> 

    <OPTIONS> 
      <OPTION_ID>1</OPTION_ID> 
      <DESCRIPTION>blah blah blah ...</DESCRIPTION> 
    </OPTIONS> 

    <PROMOTIONS> 
      <PROMOTION_ID>1</PROMOTION_ID> 
      <DESCRIPTION>blah blah blah ...</DESCRIPTION> 
    </PROMOTIONS> 

</BEGIN> 

这是迄今为止样式表:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions"> 
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/> 

    <xsl:param name="mandatoryNodes" as="xs:string*" select=" 'PRODUCTS', 'OPTIONS', 'PROMOTIONS' "/> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="child::node()"/> 
    </xsl:template> 

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

    <xsl:template match="BEGIN"> 
     <xsl:element name="BEGIN"> 
      <xsl:for-each select="$mandatoryNodes"> 
       <!-- If there is no node with this name --> 
       <xsl:if test="count(*[name() = 'current()']) = 0"> 
        <xsl:element name="{current()}" /> 
       </xsl:if> 
      </xsl:for-each> 
      <xsl:apply-templates select="child::node()"/> 
     </xsl:element> 
    </xsl:template> 

</xsl:stylesheet> 

我试着在XML间谍改造,xsl:if测试失败说,“目前的产品产品键入xs:string。

我已经尝试过相同的xsl:如果在for-each之外,它似乎工作......我错过了什么?

<xsl:for-each select="$mandatoryNodes">的内部,上下文项是一个字符串,但您想要访问主输入文档及其节点,因此您需要将该文档或模板的上下文节点存储在变量中,然后使用该节点。

<xsl:template match="BEGIN"> 
    <xsl:variable name="this" select="."/> 
    <xsl:element name="BEGIN"> 
     <xsl:for-each select="$mandatoryNodes"> 
      <!-- If there is no child node of `BEGIN` with this name --> 
      <xsl:if test="count($this/*[name() = current()]) = 0"> 
       <xsl:element name="{current()}" /> 
      </xsl:if> 
     </xsl:for-each> 
     <xsl:apply-templates select="child::node()"/> 
    </xsl:element> 
</xsl:template> 
+0

感谢您的直接答复! – Nikko