2011-02-09 84 views
3

another thread有關使用XSLT列出在XML文件中的每個節點,亞歷杭德羅提供this useful piece of XPath 2.0 code:獲取/上下文節點的文檔孩子使用XPath

編輯:我的下面,現在的樣式表使用代碼的修改後的版本,亞歷杭德羅·慈祥發佈在評論中。它報告元素的@name屬性。

我有重大的修改,它適用於像下面這樣的架構的.xsd:

示例模式

(簡化這個source的版本)

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
<xsd:annotation> 
    <xsd:documentation xml:lang="en"> 
Purchase order schema for Example.com. 
Copyright 2000 Example.com. All rights reserved. 
</xsd:documentation> 
</xsd:annotation> 
<xsd:element name="comment" type="xsd:string"> 
    <xsd:annotation> 
     <xsd:documentation>doc for comment</xsd:documentation> 
    </xsd:annotation> 
</xsd:element> 
<xsd:complexType name="USAddress"> 
    <xsd:annotation> 
     <xsd:documentation>doc for USAddress</xsd:documentation> 
    </xsd:annotation> 
    <xsd:sequence> 
     <xsd:element name="name" type="xsd:string"/> 
     <xsd:element name="street" type="xsd:string"/> 
     <xsd:element name="city" type="xsd:string"/> 
     <xsd:element name="state" type="xsd:string"/> 
     <xsd:element name="zip" type="xsd:decimal"/> 
    </xsd:sequence> 
    <xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/> 
</xsd:complexType> 
<!-- Stock Keeping Unit, a code for identifying products --> 
<xsd:simpleType name="SKU"> 
    <xsd:annotation> 
     <xsd:documentation>doc for SKU</xsd:documentation> 
    </xsd:annotation> 
    <xsd:restriction base="xsd:string"> 
     <xsd:pattern value="\d{3}-[A-Z]{2}"/> 
    </xsd:restriction> 
</xsd:simpleType> 
</xsd:schema> 
我的XSLT樣式表:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
<xsl:template match="*|@*"> 
<xsl:value-of select=" 
string-join(
distinct-values(
(//*|//@*) 
/string-join(
(ancestor::node()/name(), 
if (self::attribute()) 
    then concat('@',name()) 
    else if (self::*[@name]) 
     then concat(name(),'[@name=&quot;',@name,'&quot;]') 
     else name()), 
'/')), 
'&#xA;') 
"/> 
    </xsl:template> 
    </xsl:stylesheet> 
結果:
/xsd:schema 
/xsd:schema/xsd:annotation 
/xsd:schema/xsd:annotation/xsd:documentation 
/xsd:schema/xsd:annotation/xsd:documentation/@xml:lang 
/xsd:schema/xsd:element[@name="comment"] 
/xsd:schema/xsd:element/@name 
/xsd:schema/xsd:element/@type 
/xsd:schema/xsd:element/xsd:annotation 
/xsd:schema/xsd:element/xsd:annotation/xsd:documentation 
/xsd:schema/xsd:complexType[@name="USAddress"] 
/xsd:schema/xsd:complexType/@name 
/xsd:schema/xsd:complexType/xsd:annotation 
/xsd:schema/xsd:complexType/xsd:annotation/xsd:documentation 
/xsd:schema/xsd:complexType/xsd:sequence 
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element[@name="name"] 
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element/@name 
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element/@type 
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element[@name="street"] 
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element[@name="city"] 
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element[@name="state"] 
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element[@name="zip"] 
/xsd:schema/xsd:complexType/xsd:attribute[@name="country"] 
/xsd:schema/xsd:complexType/xsd:attribute/@name 
/xsd:schema/xsd:complexType/xsd:attribute/@type 
/xsd:schema/xsd:complexType/xsd:attribute/@fixed 
/xsd:schema/xsd:simpleType[@name="SKU"] 
/xsd:schema/xsd:simpleType/@name 
/xsd:schema/xsd:simpleType/xsd:annotation 
/xsd:schema/xsd:simpleType/xsd:annotation/xsd:documentation 
/xsd:schema/xsd:simpleType/xsd:restriction 
/xsd:schema/xsd:simpleType/xsd:restriction/@base 
/xsd:schema/xsd:simpleType/xsd:restriction/xsd:pattern 
/xsd:schema/xsd:simpleType/xsd:restriction/xsd:pattern/@value 

這個輸出很好,就這個問題而言。

現在,而不是問「我的fugly代碼有什麼問題?」我會問從實際工作的基本狀態開始的最佳方式。

我需要添加一個子句,對於每一行有/xsd:documentation的孫子,請附加文本<xsd:documentation>foo</xsd:documentation>。所以這條線:

/xsd:schema/xsd:element[@name="comment"] 

變爲:

/xsd:schema/xsd:element[@name="comment"] | doc for comment 

謝謝, 馬特

+0

好問題,+1。查看我的答案以獲得完整而簡單的解決方案。 – 2011-02-09 20:25:59

+1

除了@Dimitre很好的答案,我會繼續給你表達語義:最外層的`string-join()`它只是一個美化器; `distinct-values()`用於去除重複路徑; `(// * | // @ *)`是生成器,它表示*「來自整個文檔的任何元素和屬性」*;最內層的`string-join()`實際上是來自[specs](http://www.w3.org/TR/xquery-operators/#func-string-join)的修改路徑生成器,它使用`node ()`選擇根(空QName); 'if'表達式只是爲屬性的路徑添加`@`字符(也許我應該使用``instance`` – 2011-02-10 00:14:42

回答

3

解決方法很簡單

0.1。在樣式表中定義xsd名稱空間:

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
> 

.2。變化:

.//documentation 

.//xsd:documentation 

順便說一句,這是錯誤的

//xsd|//@* 

沒有在文檔中命名xsd元素。也許你想:

//xsd:*|//@* 

而且,也沒有必要對屬性使用local-name(),只是name()是OK。

第二個觀察:

沒有什麼錯亞歷杭德羅的解決方案。適用於它產生下列正確的輸出提供的XML文檔:

/xsd:schema 
/xsd:schema/xsd:annotation 
/xsd:schema/xsd:annotation/xsd:documentation 
/xsd:schema/xsd:annotation/xsd:documentation/@xml:lang 
/xsd:schema/xsd:element 
/xsd:schema/xsd:element/@name 
/xsd:schema/xsd:element/@type 
/xsd:schema/xsd:element/xsd:annotation 
/xsd:schema/xsd:element/xsd:annotation/xsd:documentation 
/xsd:schema/xsd:complexType 
/xsd:schema/xsd:complexType/@name 
/xsd:schema/xsd:complexType/xsd:sequence 
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element 
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element/@name 
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element/@type 
/xsd:schema/xsd:complexType/xsd:attribute 
/xsd:schema/xsd:complexType/xsd:attribute/@name 
/xsd:schema/xsd:complexType/xsd:attribute/@type 
/xsd:schema/xsd:complexType/xsd:attribute/@fixed 
/xsd:schema/xsd:complexType/xsd:annotation 
/xsd:schema/xsd:complexType/xsd:annotation/xsd:documentation 
/xsd:schema/xsd:simpleType 
/xsd:schema/xsd:simpleType/@name 
/xsd:schema/xsd:simpleType/xsd:restriction 
/xsd:schema/xsd:simpleType/xsd:restriction/@base 
/xsd:schema/xsd:simpleType/xsd:restriction/xsd:pattern 
/xsd:schema/xsd:simpleType/xsd:restriction/xsd:pattern/@value 
/xsd:schema/xsd:simpleType/xsd:annotation 
/xsd:schema/xsd:simpleType/xsd:annotation/xsd:documentation 
0

.//xsd:documentation試圖讓所有的文件兒童模式。我通過使用./xsd:documentation來解決問題。

,報告文檔,測試後的任何元素,看它是否是一個屬性的新條款:

concat(
if (self::*[@name]) 
then @name 
else name() 
, ./xsd:documentation) 

感謝大家的幫助。