在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="',@name,'"]')
else name()),
'/')),
'
')
"/>
</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
謝謝, 馬特
好問題,+1。查看我的答案以獲得完整而簡單的解決方案。 – 2011-02-09 20:25:59
除了@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