2012-09-07 30 views
0

我有下面的XML:XSLT轉換與maxOcurs序列=無限嵌套元素

<person-list> 
    <pid>100</pid> 
    <pname>Tom Jones</pname> 
    <pdescription>Some Text</pdescription> 
    <pid>101</pid> 
    <pname>John Thomas</pname> 
</person-list> 

我希望得到以下結果:

<person-list> 
    <person> 
    <pid>100</pid> 
    <pname>Tom Jones</pname> 
    <pdescription>Some Text</pdescription> 
    </person> 
    <person> 
    <pid>101</pid> 
    <pname>John Thomas</pname> 
    </person> 
</person-list> 

是否有可能實現這一目標?

+1

答案是 「是」!您是使用XSLT1.0還是XSLT2.0?它總是有助於展示您迄今爲止嘗試過的XSLT,並對轉換規則進行更多解釋。另外,我不確定問題的標題是如何提及「maxOccurs = unbounded」的序列,與問題本身有關。 –

+0

XML在我的XSD架構中被定義爲<序列maxOccurs =「unbounded」> .... 我無法想出一個更好的名字。 – Maddin

回答

1

XSLT 2.0解決方案:

<xsl:template match="person-list"> 
    <xsl:copy> 
    <xsl:for-each-group select="*" group-starting-with="pid"> 
     <person> 
     <xsl:copy-of select="current-group()"/> 
     </person> 
    </xsl:for-each-group> 
    </xsl:copy> 
</xsl:template> 
0

是的,有辦法做到這一點。你可以爲實例找到「PID」 -elements,然後使用下面的2個元素「後續兄弟」,並刪除複製的標籤將它們結合起來:

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

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

<xsl:template match="/person-list/pid"> 
<person> 
    <pid><xsl:value-of select="." /></pid> 
    <pname><xsl:value-of select="following-sibling::*" /></pname> 
    <pdescription><xsl:value-of select="following-sibling::*/following-sibling::*" /> </pdescription> 
</person> 
</xsl:template> 
<xsl:template match="/person-list/pname" /> 
<xsl:template match="/person-list/pdescription"/> 

</xsl:stylesheet> 
+0

我應該提到元素是可選的。所以我需要一些動態的方法來弄清楚何時開始下一個元素。 – Maddin

+0

然後邁克爾凱假設的xslt 2.0解決方案應該做的伎倆 - 如果您使用xslt 2.0當然 – ChriPf

+0

嗯... - 我會很感激意見downvotes工作的答案 – ChriPf

2

的一種方式做到這一點在XSLT1.0被定義該組下人名單非PID元素,由第一最前面PID元素

<xsl:key 
    name="fields" 
    match="person-list/*[not(self::pid)]" 
    use="generate-id(preceding-sibling::pid[1])" /> 

然後,對於人名單元素,你會只選擇PID的關鍵使用密鑰元素

<xsl:apply-templates select="pid" /> 

而且該PID匹配的模板內,你將創建一個元素,和輸出其他元素:

<xsl:apply-templates select="key('fields', generate-id())" /> 

下面是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:key name="fields" match="person-list/*[not(self::pid)]" use="generate-id(preceding-sibling::pid[1])" /> 
    <xsl:template match="person-list"> 
     <person-list> 
     <xsl:apply-templates select="pid" /> 
     </person-list> 
    </xsl:template> 

    <xsl:template match="pid"> 
     <person> 
     <xsl:copy-of select="." /> 
     <xsl:apply-templates select="key('fields', generate-id())" /> 
     </person> 
    </xsl:template> 

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

當應用於您的示例XML時,以下是ou輸入

<person-list> 
    <person> 
    <pid>100</pid> 
    <pname>Tom Jones</pname> 
    <pdescription>Some Text</pdescription> 
    </person> 
    <person> 
    <pid>101</pid> 
    <pname>John Thomas</pname> 
    <pdescription></pdescription> 
    </person> 
</person-list> 

請注意,使用方法您可以爲每個人添加更多字段給您輸入文檔,而不需要修改XSLT。

另請注意,使用「身份轉換」複製現有元素。