2010-10-01 93 views
1

再次是一件簡單的事情。我有一個分析XML和XSL文件的樣式表。基本上,它試圖檢測XML是否是樣式表:檢測XML文件是否包含特定命名空間

<xsl:if test="count(//xsl:template)!=0"> 

它確實檢測樣式表。但是,它具有XML文件的問題,它會生成「未定義的命名空間前綴 - 'xsl'」錯誤。 (在XmlSpy中,我正在處理的項目中出現類似錯誤。)

我做錯了什麼。有關如何改進此樣式表的任何建議?


一些額外的信息:這是一個的意思分析其他的XML文件,無論它們包含內容的樣式表。它應該能夠自我改變,並且做得很好。轉換其他(普通)樣式表也沒有問題。當我嘗試轉換常規的XML文件時,問題就到了。然而並非所有的XML文件...


事實證明,錯誤是別的。我試圖轉換的XML文件包含處理指令。這一個:<?xml-stylesheet href="..\MyStylesheet.xsl" type="text/xsl"?>
我現在的問題是,當我處理包含此PI的XML文件時,XSLT開始報告有關未定義名稱空間前綴的錯誤。那麼,我該如何告訴XSLT處理器忽略這個處理指令呢?

+0

亞歷克斯:這是一個奇怪的錯誤報告。如果查詢沒有XSLT名稱空間的XML樹,它應該導致一個空的節點集,而不是一個錯誤。 – 2010-10-01 12:11:07

+0

好問題(+1)。查看我的答案以獲得詳細的分析和簡短而全面的解決方案。 – 2010-10-01 13:05:30

回答

1

仔細檢查您聲明xsl命名空間的方式以及您選擇的命名空間前綴。

如果要在XPATH表達式中使用它,則需要確保在樣式表中定義了xsl命名空間前綴。當您嘗試使用尚未聲明的名稱空間前綴時,將會出現該錯誤。

如果沒有在樣式表(通常這樣的文檔元素:<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">)宣佈任何地方進一步上漲,或者如果你選擇了一個不同的命名空間的前綴(例如,宣稱其爲「XSLT」是這樣的: xmlns:xslt="http://www.w3.org/1999/XSL/Transform"),那麼當您嘗試引用「xsl」時,它將不知道您所指的是什麼。

您可以在if聲明聲明xsl命名空間前綴作爲一個快速測試:

<xsl:if test="count(//xsl:template)!=0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

,關於如何提高這個 樣式表有什麼建議?

您可以簡化測試條件來選擇xsl:template元素,而不是評估它們的count()。如果選擇了某些內容,test="//xsl:template"的結果將評估爲true(),如果沒有選擇任何內容,則結果爲false()

樣式表xsl:template是頂層構造,它們是文檔元素的子元素。而不是使用//通過在XML文檔樹的每個節點遞歸,您可以使用更高效的XPath表達式:

<xsl:if test="/*/xsl:template" /> 
1

這是不正確的假設一個XSLT代碼文件總是包含<xsl:template>指令

有一些XSLT樣式表模塊的例子,其中文件只包含一個<xsl:stylesheet>指令和一個或多個全局級變量。這種樣式表模塊通常使用<xsl:import><xsl:include>指令導入/包含在另一個樣式表模塊中。

此外,定義XSLT的不是構成XSLT指令的元素的前綴。此前綴不強制爲"xsl",某些程序員使用不同的前綴,例如"xslt""x"

真正定義XSLT代碼的是XSLT命名空間

最後,XSLT代碼文件不能保證甚至包含<xsl:stylesheet>指令,因爲XSLT提供了一個同義詞:<xsl:transform>

考慮在帳戶中的所有這些考慮,更好的測試將是:

/*[contains('|stylesheet|transform|', concat('|', local-name(), '|') 
      and 
      namespace-uri()="http://www.w3.org/1999/XSL/Transform" 
      ) 

由於存在具有embedded stylesheets的可能性,上述試驗可以稍加修改,以覆蓋這些以及:

//*[contains('|stylesheet|transform|', concat('|', local-name(), '|') 
      and 
      namespace-uri()="http://www.w3.org/1999/XSL/Transform" 
      ) 
+0

我知道這是不正確的,但如果沒有,我不想顯示任何信息。使用樣式表時,我只收集@match,@mode和@name屬性以顯示在報表中。該系統只是試圖檢測XML文件是否是我定義的任何已知類型。如果沒有,這不是很有趣。不過,非常好的一點! – 2010-10-01 13:42:11

0

爲什麼您需要檢查「/ xsl:template | xsl:transform」之外的任何內容?那些必須處於頂級水平,並且只有才能處於頂級水平。

+0

我不需要。但是XML文件可能是或者可能不是XSLT文件。我正在處理的項目從特殊資源接收XML數據,需要檢測它是什麼並提供有關內容的信息。使用XSLT文件,我需要列出模板。對於其他XML文件,我需要從40個不同的文件中檢查它的格式並顯示它的內容。這就是所要做的。 – 2010-10-17 12:56:27