2013-03-05 64 views
0

我想老XML文件轉換成新的和改進的結構。這部分需要我來包裝一些鬆散的元素融入到父容器,以及修改自己的孩子使用XSLT來包裝的元素,但不包括最後一個匹配的元素

舊結構

<monograph> 
    <title>asdf</title> 

    <dosage.sec id="dosage.sec.1"> 
    <dosage.sec>asgfd</dosage.sec> 
    <dosage.sec>asgfd</dosage.sec> 
    </dosage.sec> 
    <dosage.sec id="dosage.sec.2"> 
    <dosage.sec>asgfd</dosage.sec> 
    <dosage.sec>asgfd</dosage.sec> 
    </dosage.sec> 
    <dosage.sec id="dosage.sec.3"> 
    <dosage.sec>asgfd</dosage.sec> 
    <dosage.sec>asgfd</dosage.sec> 
    </dosage.sec> 

    <products> 
    <prod>sadf</prod> 
    <prod>sadf</prod> 
    </products> 
</monograph> 

新結構

<monograph> 
    <title>asdf</title> 

    <dosage> 
    <dosage.sec id="dosage.sec.1"> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    <dosage.sec id="dosage.sec.2"> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    <dosage.sec id="dosage.sec.3"> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    </dosage> 

    <products> 
    <prod>sadf</prod> 
    <prod>sadf</prod> 
    </products> 
</monograph> 

我發現這answer和修改它有點適合我的需要:

<!-- wrap dosage.sec elements in a dosage container --> 
<xsl:template match="node()|@*" name="dosage.sec"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*" /> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="monograph/dosage.sec[not(preceding-sibling::*[1][self::dosage.sec])]"> 
    <dosage> 
     <xsl:call-template name="dosage.sec" /> 
     <xsl:apply-templates mode="copy" select="following-sibling::*[1][self::dosage.sec]" /> 
    </dosage> 
</xsl:template> 

<xsl:template match="monograph/dosage.sec" mode="copy"> 
    <xsl:call-template name="dosage.sec"/> 
</xsl:template> 


<!-- rename children dosage.sec --> 
<xsl:template match="dosage.sec/dosage.sec"> 
    <dosage.qual> 
     <xsl:apply-templates /> 
    </dosage.qual> 
</xsl:template> 

但我的輸出是:

<monograph> 
    <title>asdf</title> 

    <dosage> 
    <dosage.sec id="dosage.sec.1"> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    <dosage.sec id="dosage.sec.2"> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    <dosage.sec id="dosage.sec.3"> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    </dosage> 

    <dosage.sec id="dosage.sec.3"> 
    <dosage.qual>asgfd</dosage.qual> 
    <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 

    <products> 
    <prod>sadf</prod> 
    <prod>sadf</prod> 
    </products> 
</monograph> 

我使用PHP5內建的XSLTProcessor中的對象 - 所有的XML和XSL是1.0版

+0

如果你刪除你的XSLT可能會工作的'[1]'從這一行:'的'但是你的方式可能不是最好的方法。 – JLRishe 2013-03-05 10:34:03

+0

你提到的答案是解決一個特定的場景,他們需要在他們之前和之後包裝具有不同項目的物品。你有這樣的要求,還是像你的例子一樣簡單? – JLRishe 2013-03-05 16:19:24

+0

所有dose.sec元素應該在源文檔中連續(中間沒有其他元素),因此它更簡單。我已經修改了我的例子,因爲我意識到我沒有準確地描述在該劑量塊之前和之後的專論中我還有其他元素。 – HorusKol 2013-03-05 22:58:00

回答

0

我在路上遇到了一些其他問題 - 例如,我發現dose.sec元素不在連續區域,我錯誤地創建了兩個劑量容器。

這些模板解決我的問題:

<!-- wrap dosage.sec elements in a dosage container --> 
<xsl:template match="monograph/dosage.sec" name="dosage.sec"> 
    <xsl:param name="drugname" /> 

    <xsl:copy> 
     <xsl:apply-templates> 
      <xsl:with-param name="drugname" select="$drugname" /> 
     </xsl:apply-templates> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="monograph/dosage.sec[not(preceding::dosage.sec)]"> 
    <xsl:param name="drugname" /> 

    <dosage> 
     <xsl:call-template name="dosage.sec"> 
      <xsl:with-param name="drugname" select="$drugname" /> 
     </xsl:call-template> 

     <xsl:apply-templates mode="copy" select="following::dosage.sec"> 
      <xsl:with-param name="drugname" select="$drugname" /> 
     </xsl:apply-templates> 
    </dosage> 
</xsl:template> 

<xsl:template match="monograph/dosage.sec" mode="copy"> 
    <xsl:param name="drugname" /> 

    <xsl:call-template name="dosage.sec"> 
     <xsl:with-param name="drugname" select="$drugname" /> 
    </xsl:call-template> 
</xsl:template> 

<xsl:template match="monograph/dosage.sec[(preceding::dosage.sec)]" /> 
2

如何:

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

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

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

    <!-- rename children dosage.sec --> 
    <xsl:template match="dosage.sec/dosage.sec"> 
    <dosage.qual> 
     <xsl:apply-templates /> 
    </dosage.qual> 
    </xsl:template> 
</xsl:stylesheet> 

當運行你的樣品輸入,產生:

<monograph> 
    <dosage> 
    <dosage.sec> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    <dosage.sec> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    <dosage.sec> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    </dosage> 
</monograph> 
相關問題