2011-05-20 23 views
2

我有以下簡單的XML結構:檢查子節點的存在和應用模板

<?xml version="1.0" encoding="UTF-8"?> 
<ExportData> 
<TransportHeader> 
    <Timestamp>2011-01-16 06:00:33</Timestamp> 
    <From> 
     <Name>DynamicExport</Name> 
     <Version>1.</Version> 
    </From> 
    <MessageId>d7b5c5b69a83</MessageId> 
</TransportHeader> 
<ExportConfig> 
    <DateTimeFormat>yyyy-MM-dd HH:mm:ss</DateTimeFormat> 
    <DecimalSymbol>.</DecimalSymbol> 
</ExportConfig> 
<DataSet> 
    <Tables> 
     <Table> 
      <RH>...</RH> 
      <Rows> 
       <R>Data1</R> 
       <R>Data2</R> 
       <R>Data3</R> 
       <R>Data4</R> 
       <R>Data5</R> 
      </Rows> 
     </Table> 
    </Tables> 
</DataSet> 
</ExportData> 

我要檢查是否存在或不<R>元素。如果不存在<R>元素,則映射必須中止,否則需要創建每<R><Line>元素。

我想出了這個解決方案,它完美的作品至今:

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

<!-- suppress nodes that are not matched --> 
<xsl:template match="text() | @*"> 
    <xsl:apply-templates select="text() | @*"/> 
</xsl:template> 

<xsl:template match="/"> 
    <xsl:choose> 
     <xsl:when test="not(ExportData/DataSet/Tables/Table/Rows/node())"> 
      <xsl:message terminate="yes">No line items</xsl:message> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:apply-templates/> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

<xsl:template match="/ExportData/DataSet/Tables/Table/Rows"> 
    <INVOIC02> 
     <!-- apply LINE ITEMS template --> 
     <xsl:apply-templates select="R"/> 
    </INVOIC02> 
</xsl:template> 

<!-- Template creating LINE ITEMS --> 
<xsl:template match="R"> 

    <Line> 
     <elements></elements> 
    </Line> 
</xsl:template> 


</xsl:stylesheet> 

如果有<R>元素的輸出是這樣的:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<INVOIC02> 
<Line> 
    <elements/> 
</Line> 
<Line> 
    <elements/> 
</Line> 
<Line> 
    <elements/> 
</Line> 
<Line> 
    <elements/> 
</Line> 
<Line> 
    <elements/> 
</Line> 
</INVOIC02> 

如果只是<Rows/>並沒有<R> S中映射被中止。

現在我有兩個問題:

-Is我測試<R>元素穩健:test="not(ExportData/DataSet/Tables/Table/Rows/node())"

- 我正在使用<xsl:apply-templates>創建<Line>項目而不是<xsl:for-each>構造。我的XPath表達式好嗎,還是可以讓它們變得更好?

謝謝你對此的任何迴應或建議。

最好的問候, 彼得

回答

5

是我強大的元素測試:測試= 「沒有(ExportData /數據集/表/表/行/節點())」 ?

好了,你想,如果沒有R元素,如果Rows沒有一個孩子node(),其中包括它失敗,還是失敗任何元素(不只是R),text()comment()processing-instruction()

如果你真的想驗證是否存在至少一個R元素是Rows一個孩子,你應該調整測試標準更加具體:

test="not(ExportData/DataSet/Tables/Table/Rows/R)" 

否則,可能會通過即測試並繼續處理,不生成您想要的內容。

I am using <xsl:apply-templates> to create the <Line> items instead of an 
<xsl:for-each> construct. 
Are my XPath expressions okay or could I make them better? 

你可以擺脫<xsl:if>條件邏輯內模板的根節點並移動邏輯轉化爲Rows模板不包含R孩子。將邏輯放入xsl:template@match條件可以讓XSLT處理器更易於優化,從而提高性能。

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

    <!-- suppress nodes that are not matched --> 
    <xsl:template match="text() | @*"> 
     <xsl:apply-templates select="text() | @*"/> 
    </xsl:template> 

    <!--All Rows must contain an R. 
     If we encounter any that do not, terminate the transform --> 
    <xsl:template match="/ExportData/DataSet/Tables/Table/Rows[not(R)]"> 
     <xsl:message terminate="yes">No line items</xsl:message> 
    </xsl:template> 

    <!--match for Rows that have R children --> 
    <xsl:template match="/ExportData/DataSet/Tables/Table/Rows[R]"> 
     <INVOIC02> 
      <!-- apply LINE ITEMS template --> 
      <xsl:apply-templates select="R"/> 
     </INVOIC02> 
    </xsl:template> 

    <!-- Template creating LINE ITEMS --> 
    <xsl:template match="R">  
     <Line> 
      <elements></elements> 
     </Line> 
    </xsl:template> 

</xsl:stylesheet> 
+0

謝謝你們的解釋!如果沒有元素,我希望它失敗,所以我必須使搜索條件更具體。額外的模板,而不是我的邏輯工作完美 - 感謝那個「伎倆」。最好的問候,彼得 – Peter 2011-05-23 09:33:45

0

只是檢查

<xsl:if test="R"> 
    <!--What you want to do here--> 
</xsl:if> 

這將檢查[R節點是否有子元素。

Buddhistika

相關問題