2015-11-17 46 views
0

我需要重寫一組<p><lb>節點。這是我最初的節點集:用xslt添加和重新排列節點來重寫XML生成的樹

<p> 
    text[1] and nodes[1] here 
    <pb/> 
    text[2] and nodes[2] here 
    <pb/> 
    text[3] and nodes[3] here 
    <pb/> 
    [...] 
    text[x] and any nodes[x] here 
</p> 

而這正是我需要的:

<p>text[1] and nodes[1] here</p> 
<pb/> 
<p>text[2] and nodes[2] here</p> 
<pb/> 
<p>text[3] and nodes[3] here</p> 
<pb/> 
<p>[...]</p> 
<p>text[x] and nodes[x] here</p> 

我設法爲進一步轉變變量撞他們重寫第一個和最後一個節點和文本:

<xsl:variable name="textAndNotes_1"> 
    <p> 
     <xsl:copy-of select=" child::node()[not(preceding-sibling::*:pb) 
     and not(self::*:pb)]"/> 
    </p> 
</xsl:variable> 

[...] 

<xsl:variable name="textAndNotes_x"> 
    <p> 
     <xsl:copy-of select="child::node()[not(following-sibling::*:pb) and 
     not(self::*:pb)]"/> 
    </p> 
</xsl:variable> 

這也適用於第一個和最後一個<pb/>。但我與內部<p>...</p>和內部<pb/>疊加,我不確定這是做到這一點的正確方法。我一直在尋找幾個小時而沒有找到答案。任何幫助?

所有最好的,特里斯坦

+0

您可以使用XSLT 2.0嗎? –

+0

是的,我可以使用XSLT 2.0。在此先感謝... T – Tristan

+0

是不是''你想要包裝成'p'元素的真實內容?你能解釋哪些內容應該被包裝進一個'p'元素,哪一個不是? –

回答

0

以下樣式表:

XSLT 2.0

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

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

<xsl:template match="p"> 
    <xsl:for-each-group select="node()" group-starting-with="pb"> 
     <p> 
      <xsl:apply-templates select="current-group()[not(self::pb)]" /> 
     </p>  
    </xsl:for-each-group> 
</xsl:template> 

</xsl:stylesheet> 

當施加到下面的測試輸入:

XML

<root> 
    <p> 
     text[1] and nodes[1] here 
     <pb/> 
     text[2] and nodes[2] here 
     <pb/> 
     text[3] and nodes[3] here 
     <pb/> 
     [...] 
     text[x] and any nodes[x] here 
    </p> 
</root> 

將返回:

結果

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <p> 
     text[1] and nodes[1] here 
     </p> 
    <p> 
     text[2] and nodes[2] here 
     </p> 
    <p> 
     text[3] and nodes[3] here 
     </p> 
    <p> 
     [...] 
     text[x] and any nodes[x] here 
    </p> 
</root> 

注意,這個假設所有<pb/>分頻器是p直接孩子。

+0

爲什麼在結果中沒有''?問題中的請求輸出包含它們。 –

+0

@MartinHonnen它呢?我努力去除它們。無論如何,這是一個簡單的修復方法來保留它們。但OP需要先澄清。 –

+0

這工作就像一個魅力。我沒有想到''解決了這個問題。只需爲''添加一個小小的'。非常感謝,邁克爾! – Tristan

0

要XSL我knowledege水平,它出來有點複雜的XSL,但在這裏它是:

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

<xsl:template match="/root"> 
<root> 
    <xsl:apply-templates select="p"/> 
</root> 
</xsl:template> 

<xsl:template match="p"> 
    <!--Counts the number of groups and calls the iterator template--> 
    <xsl:call-template name="print-all-groups"><xsl:with-param name="numgroups" select="count(pb)"/><xsl:with-param name="index" select="0"/></xsl:call-template> 
</xsl:template> 

<xsl:template name="print-all-groups"> 
    <!--Iterates the child groups of P: from the index-th to the numgroups-th--> 
    <xsl:param name="numgroups"></xsl:param> 
    <xsl:param name="index"></xsl:param> 
    <xsl:call-template name="print-group"><xsl:with-param name="index" select="$index"></xsl:with-param></xsl:call-template> 
    <xsl:if test="$index &lt; $numgroups"> 
     <xsl:call-template name="print-all-groups"><xsl:with-param name="numgroups" select="$numgroups"/><xsl:with-param name="index" select="1+$index"/></xsl:call-template> 
    </xsl:if> 
</xsl:template> 

<xsl:template name="print-group"> 
    <!--Selects the first node after the index-th group and processes it (applies the 'group-item' templates)--> 
    <xsl:param name="index"></xsl:param> 
    <xsl:if test="$index=0"> 
     <p><xsl:apply-templates select="(text()|*)[1]" mode="group-item"></xsl:apply-templates></p> 
    </xsl:if> 
    <xsl:if test="not($index=0)"> 
     <p><xsl:apply-templates select="(pb[$index]/following-sibling::text()|pb[$index]/following-sibling::*)[1]" mode="group-item"></xsl:apply-templates></p> 
    </xsl:if> 
    <pb/> 
</xsl:template> 

<xsl:template match="*" mode="group-item"> 
    <!--Copies the current node and iterates to the following sibling until a PB is found--> 
    <xsl:if test="name(.) !='pb'"> 
     <xsl:copy-of select="current()"/> 
     <xsl:apply-templates select="(following-sibling::text()|following-sibling::*)[1]" mode="group-item"></xsl:apply-templates> 
    </xsl:if> 
</xsl:template> 

<xsl:template match="text()" mode="group-item"> 
    <!--Copies the current node and iterates to the following sibling--> 
    <xsl:copy-of select="current()"/> 
    <xsl:apply-templates select="(following-sibling::text()|following-sibling::*)[1]" mode="group-item"></xsl:apply-templates> 
</xsl:template> 

</xsl:stylesheet> 

唯一的「絕招」就是它總是打印每個組後<pb>節點。這是錯的嗎?

我這個XML測試它:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<root> 
    <p> 
     text1<month>january</month><day>monday</day> 
     <pb/> 
     text2<month>february</month><day>tuesday</day> 
     <pb/> 
     text3<month>march</month><day>wednesday</day> 
    </p> 
</root> 

...它產生這樣的輸出:

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
<p> 
     text1<month>january</month> 
<day>monday</day> 
</p> 
<pb/> 
<p> 
     text2<month>february</month> 
<day>tuesday</day> 
</p> 
<pb/> 
<p> 
     text3<month>march</month> 
<day>wednesday</day> 
</p> 
<pb/> 
</root> 
+0

非常感謝。馬丁的解決方案有點不太密集,但我會在其他情況下考慮這一策略。 – Tristan

+0

是的,它有點密集,我知道...... :-)不客氣。 –