2013-05-13 115 views
0

我有一個以下結構的文檔(這只是幫助我表達問題的一個示例),我試圖將其展平。通過壓扁我的意思是複製所有<Report_Entry>節點與幾個<Event>這麼每個<Report_Entry>節點包含只是一個單一的<Event>使用XSLT展開具有重複子節點的節點

我有什麼:

<?xml version="1.0"?> 
<Report_Data> 
    <Report_Entry> 
    <ID>1</ID> 
    <Event> 
     <Start_Date>2011-09-06</Start_Date> 
     <End_Date>2011-09-10</End_Date> 
    </Event> 
    <Event> 
     <Start_Date>2011-09-10</Start_Date> 
     <End_Date>2011-09-15</End_Date> 
    </Event> 
    <Event> 
     <Start_Date>2011-09-15</Start_Date> 
     <End_Date>2011-09-20</End_Date> 
    </Event> 
    </Report_Entry> 
    <Report_Entry> 
    <ID>2</ID> 
    <Event> 
     <Start_Date>2011-09-20</Start_Date> 
     <End_Date>2011-09-25</End_Date> 
    </Event> 
    <Event> 
     <Start_Date>2011-09-25</Start_Date> 
     <End_Date>2011-09-30</End_Date> 
    </Event> 
    </Report_Entry> 
    <Report_Entry> 
    <ID>3</ID> 
    <Event> 
     <Start_Date>2011-09-30</Start_Date> 
     <End_Date>2011-10-05</End_Date> 
    </Event> 
    </Report_Entry> 
</Report_Data> 

我試圖讓:

<?xml version="1.0"?> 
<Report_Data> 
    <Report_Entry> 
    <ID>1</ID> 
    <Event> 
     <Start_Date>2011-09-06</Start_Date> 
     <End_Date>2011-09-10</End_Date> 
    </Event> 
    </Report_Entry> 
    <Report_Entry> 
    <ID>1</ID> 
    <Event> 
     <Start_Date>2011-09-10</Start_Date> 
     <End_Date>2011-09-15</End_Date> 
    </Event> 
    </Report_Entry> 
    <Report_Entry> 
    <ID>1</ID> 
    <Event> 
     <Start_Date>2011-09-15</Start_Date> 
     <End_Date>2011-09-20</End_Date> 
    </Event> 
    </Report_Entry> 
    <Report_Entry> 
    <ID>2</ID> 
    <Event> 
     <Start_Date>2011-09-20</Start_Date> 
     <End_Date>2011-09-25</End_Date> 
    </Event> 
    </Report_Entry> 
    <Report_Entry> 
    <ID>2</ID> 
    <Event> 
     <Start_Date>2011-09-25</Start_Date> 
     <End_Date>2011-09-30</End_Date> 
    </Event> 
    </Report_Entry> 
    <Report_Entry> 
    <ID>3</ID> 
    <Event> 
     <Start_Date>2011-09-30</Start_Date> 
     <End_Date>2011-10-05</End_Date> 
    </Event> 
    </Report_Entry> 
</Report_Data> 

這裏是我正在使用的XSLT:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:template match="node() | @*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node() | @*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="Report_Entry"> 
    <xsl:for-each select="Event"> 
    <Report_Entry> 
     <xsl:copy-of select="../*[not(self::Event)]"/> 
     <xsl:copy-of select="."/> 
    </Report_Entry> 
    </xsl:for-each> 
</xsl:template> 

</xsl:stylesheet> 

雖然我覺得可能會有更好,更快,更通用的解決方案,但它起作用。特別是,我不喜歡「硬編碼」<Report_Entry>,因爲這樣我就不能複製它的屬性(如果有的話)。是否有其他方式/模板來處理這個問題?

回答

0

你的答案不能簡單得多,所以不用擔心那個方面。在編寫代碼時,尤其是XSLT時,代碼的清晰度往往比其最終效率值得多。

至於硬編碼的元素名稱和屬性複製,這裏是一個開始:

<xsl:template match="Report_Entry"> 
    <xsl:variable name="parent-name" select="name()"/> 
    <xsl:variable name="parent-attributes" select="@*"/> 
    <xsl:for-each select="Event"> 
    <xsl:element name="{$parent-name}"> 
     <xsl:copy-of select="$parent-attributes"/> 
     <xsl:copy-of select="../*[not(self::Event)]"/> 
     <xsl:copy-of select="."/> 
    </xsl:element> 
    </xsl:for-each> 
</xsl:template> 

variable s的用來藏匿一些上下文的,因爲它存在的for-each之外。 element可以讓你的原創作品看起來很像,不管它叫什麼,第一個copy-of也可以通過複製原作的屬性使它更具說服力。現在,如果您的數據突然出現屬性,您就可以做好準備了。

名字的非hardcodedness沒有多大的意義在這種情況下,但它如果說,你要的那部分分解出一個單獨的模板,並從多個地方調用它:

<xsl:template name="collapse-the-thing"> 
    <xsl:param name="context"/> 
    <xsl:param name="sub-element-name" select="'Event'"/> 
    <xsl:variable name="parent-name" select="name($context)"/> 
    <xsl:variable name="parent-attributes" select="$context/@*"/> 
    <xsl:for-each select="$context/*[name()=$sub-element-name]"> 
    <xsl:element name="{$parent-name}"> 
     <xsl:copy-of select="$parent-attributes"/> 
     <xsl:copy-of select="../*[name()!=$sub-element-name]"/> 
     <xsl:copy-of select="."/> 
    </xsl:element> 
    </xsl:for-each> 
</xsl:template> 

<xsl:template match="Report_Entry"> 
    <xsl:call-template name="collapse-the-thing"> 
    <xsl:with-param name="context" select="."/> 
    </xsl:call-template> 
</xsl:template> 

<xsl:template match="Some_Other_Entry"> 
    <xsl:call-template name="collapse-the-thing"> 
    <xsl:with-param name="context" select="."/> 
    <xsl:param name="sub-element-name" select="'Happening'"/> 
    </xsl:call-template> 
</xsl:template> 

希望是有啓發性的。請享用!

+0

非常感謝!這真的很有啓發和幫助! :)我會在稍後保存你的靈活的例子,並會利用第一個。順便說一句,如果我想在展開文檔時應用其他轉換,我可以替換,對吧? – jackzee 2013-05-13 22:31:06

+0

是啊,你可以用任何數量的其他東西替換它們(後兩個'copy-of's),這取決於你想要輸出的東西。'apply-templates'當然會將頂層'template'規則應用到當前節點的匹配子節點(在'for-each'內是你的'Event'元素)。如果您想針對這種情況應用一組單獨的規則,請參閱'mode'屬性。 – psmay 2013-05-14 13:25:19

1

像這樣簡單

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="/*"> 
    <Report_Data> 
    <xsl:apply-templates select="*/Event"/> 
    </Report_Data> 
</xsl:template> 

<xsl:template match="Event"> 
    <Report_Entry> 
    <xsl:copy-of select="../ID | ."/> 
    </Report_Entry> 
</xsl:template> 
</xsl:stylesheet> 

當這個變換所提供的XML文檔應用:

<Report_Data> 
    <Report_Entry> 
    <ID>1</ID> 
    <Event> 
     <Start_Date>2011-09-06</Start_Date> 
     <End_Date>2011-09-10</End_Date> 
    </Event> 
    <Event> 
     <Start_Date>2011-09-10</Start_Date> 
     <End_Date>2011-09-15</End_Date> 
    </Event> 
    <Event> 
     <Start_Date>2011-09-15</Start_Date> 
     <End_Date>2011-09-20</End_Date> 
    </Event> 
    </Report_Entry> 
    <Report_Entry> 
    <ID>2</ID> 
    <Event> 
     <Start_Date>2011-09-20</Start_Date> 
     <End_Date>2011-09-25</End_Date> 
    </Event> 
    <Event> 
     <Start_Date>2011-09-25</Start_Date> 
     <End_Date>2011-09-30</End_Date> 
    </Event> 
    </Report_Entry> 
    <Report_Entry> 
    <ID>3</ID> 
    <Event> 
     <Start_Date>2011-09-30</Start_Date> 
     <End_Date>2011-10-05</End_Date> 
    </Event> 
    </Report_Entry> 
</Report_Data> 

有用,正確的結果產生:

<Report_Data> 
    <Report_Entry> 
     <ID>1</ID> 
     <Event> 
     <Start_Date>2011-09-06</Start_Date> 
     <End_Date>2011-09-10</End_Date> 
     </Event> 
    </Report_Entry> 
    <Report_Entry> 
     <ID>1</ID> 
     <Event> 
     <Start_Date>2011-09-10</Start_Date> 
     <End_Date>2011-09-15</End_Date> 
     </Event> 
    </Report_Entry> 
    <Report_Entry> 
     <ID>1</ID> 
     <Event> 
     <Start_Date>2011-09-15</Start_Date> 
     <End_Date>2011-09-20</End_Date> 
     </Event> 
    </Report_Entry> 
    <Report_Entry> 
     <ID>2</ID> 
     <Event> 
     <Start_Date>2011-09-20</Start_Date> 
     <End_Date>2011-09-25</End_Date> 
     </Event> 
    </Report_Entry> 
    <Report_Entry> 
     <ID>2</ID> 
     <Event> 
     <Start_Date>2011-09-25</Start_Date> 
     <End_Date>2011-09-30</End_Date> 
     </Event> 
    </Report_Entry> 
    <Report_Entry> 
     <ID>3</ID> 
     <Event> 
     <Start_Date>2011-09-30</Start_Date> 
     <End_Date>2011-10-05</End_Date> 
     </Event> 
    </Report_Entry> 
</Report_Data> 
相關問題