2015-05-19 97 views
1

我面臨着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之外,它似乎工作......我錯過了什麼?

回答

2

<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