2011-08-30 90 views
1

我有非結構化XML的Adlib文件,它包含以下格式的數據:非結構化(的Adlib)XML使用XSLT結構化的XML,將類似節點

<record> 
    ... 
    <dimension.type>height</dimension.type> 
    <dimension.type>width</dimension.type> 
    <dimension.type>height</dimension.type> 
    <dimension.type>width</dimension.type> 
    <dimension.type>depth</dimension.type> 
    <dimension.notes>without frame</dimension.notes> 
    <dimension.notes>without frame</dimension.notes> 
    <dimension.notes>with frame</dimension.notes> 
    <dimension.notes>with frame</dimension.notes> 
    <dimension.notes>with frame</dimension.notes> 
    <dimension.value>28.0</dimension.value> 
    <dimension.value>47.9</dimension.value> 
    <dimension.value>41.4</dimension.value> 
    <dimension.value>62.9</dimension.value> 
    <dimension.value>8.0</dimension.value> 
    ... 
</record> 

我想要做的是改變這到以下格式:

<record> 
    ... 
    <dimension> 
     <notes>without frame</notes> 
     <height>28.0</height> 
     <width>47.9</width> 
    </dimension> 
    <dimension> 
     <notes>with frame</notes> 
     <height>41.4</height> 
     <width>62.9</width> 
     <depth>8.0</depth> 
    </dimension> 
    ... 
</record> 

但是我有點卡住,因爲這些節點引用其他節點在相同位置的信息。我沒有想出以下XSLT:

<xsl:template match="dimension.value"> 
    <xsl:variable name="pos" select="position()"/> 
    <dimension> 
    <xsl:choose> 
    <xsl:when test="../dimension.type[$pos] = 'height'"> 
     <height><xsl:value-of select="."/></height> 
    </xsl:when> 
    <xsl:when test="../dimension.type[$pos] = 'width'"> 
     <width><xsl:value-of select="."/></width> 
    </xsl:when> 
    <xsl:when test="../dimension.type[$pos] = 'depth'"> 
     <depth><xsl:value-of select="."/></depth> 
    </xsl:when> 
    </xsl:choose> 
    <notes> 
    <xsl:value-of select="../dimension.notes[$pos]"/> 
    </notes> 
    </dimension> 
</xsl:template> 

哪些格式生成數據:

<dimension> 
    <height>28.0</height> 
    <notes>without frame</notes> 
</dimension> 
<dimension> 
    <width>47.9</width> 
    <notes>without frame</notes> 
</dimension> 
<dimension> 
    <height>41.4</height> 
    <notes>with frame</notes> 
</dimension> 
<dimension> 
    <width>62.9</width> 
    <notes>with frame</notes> 
</dimension> 
<dimension> 
    <depth>8.0</depth> 
    <notes>with frame</notes> 
</dimension> 

但是,這並不做筆記部分分組,這將使處理結果的位更容易(現在我在代碼中解決這個問題,但是XSLT必須有一種方法來完成它,對嗎?)。任何幫助(指向相關信息或相關的XSLT片段)將不勝感激...

順便說一句我翻譯了XML/XSLT的部分,以便更容易理解,when:測試實際上檢查荷蘭語的描述和變換他們成等價的英文標籤...

+0

您可以使用XSLT 2.0具有強大'的xsl:for-每個-group'構建? –

+0

目前還沒有,不,因爲PHP(用於處理文件)仍然依賴於XSLT 1.0 ...將Java/Saxon添加到混合中以處理XML文件將會過度。 – wimvds

回答

2

這裏是一個XSLT 1.0解決方案:

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 

    <xsl:strip-space elements="*"/> 
    <xsl:output indent="yes"/> 

    <xsl:template match="record"> 
    <xsl:copy> 
     <xsl:apply-templates select="dimension.notes[1]" mode="group"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="dimension.notes" mode="group"> 
    <dimension> 
     <notes> 
     <xsl:value-of select="."/> 
     </notes> 
     <xsl:apply-templates select="."/> 
    </dimension> 
    <xsl:apply-templates select="following-sibling::dimension.notes[not(. = current())][1]" mode="group"/> 
    </xsl:template> 

    <xsl:template match="dimension.notes"> 
    <xsl:variable name="pos"> 
     <xsl:number/> 
    </xsl:variable> 
    <xsl:apply-templates select="../dimension.type[position() = $pos]"> 
     <xsl:with-param name="pos" select="$pos"/> 
    </xsl:apply-templates> 
    <xsl:apply-templates select="following-sibling::dimension.notes[1][. = current()]"/> 
    </xsl:template> 

    <xsl:template match="dimension.type"> 
    <xsl:param name="pos"/> 
    <xsl:element name="{.}"> 
     <xsl:value-of select="../dimension.value[position() = $pos]"/> 
    </xsl:element> 
    </xsl:template> 

</xsl:stylesheet> 
+0

非常感謝,這似乎是訣竅! XSLT實際上並不是我的專業領域,距離我上次使用它已經有幾年了 - 想想我最好花一些時間在它上面:p。 – wimvds

1

下面是使用XSLT 2.0的一些例子:

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs" 
    version="2.0"> 

    <xsl:strip-space elements="*"/> 
    <xsl:output indent="yes"/> 

    <xsl:template match="record"> 
    <xsl:copy> 
     <xsl:for-each-group select="dimension.notes" group-adjacent="."> 
     <dimension> 
      <notes> 
      <xsl:value-of select="current-grouping-key()"/> 
      </notes> 
      <xsl:apply-templates select="current-group()"/> 
     </dimension> 
     </xsl:for-each-group> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="dimension.notes"> 
    <xsl:variable name="pos" as="xs:integer"> 
     <xsl:number/> 
    </xsl:variable> 
    <xsl:apply-templates select="../dimension.type[position() eq $pos]"> 
     <xsl:with-param name="pos" select="$pos"/> 
    </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="dimension.type"> 
    <xsl:param name="pos"/> 
    <xsl:element name="{.}"> 
     <xsl:value-of select="../dimension.value[position() eq $pos]"/> 
    </xsl:element> 
    </xsl:template> 

</xsl:stylesheet> 

我不知道它解決您的問題,因爲「......」你的樣品中可能需要更復雜編碼,具體取決於哪些元素可以在那裏發生,以及你想要對它們做什麼。