2012-09-07 35 views
2

我試圖取代這個XML更換兩個過同級元素:XSL:一個

<name type="personal" authority="local"> 
    <namePart>Gertrude</namePart> 
    <namePart type="termsOfAddress">Aunt</namePart> 
    <role> 
    <roleTerm authority="marcrelator" type="text">Correspondent</roleTerm> 
    <roleTerm authority="marcrelator" type="code">crp</roleTerm> 
    </role> 
</name> 

與該XML:

<name type="personal" authority="local"> 
    <namePart>Aunt Gertrude</namePart> 
    <role> 
    <roleTerm authority="marcrelator" type="text">Correspondent</roleTerm> 
    <roleTerm authority="marcrelator" type="code">crp</roleTerm> 
    </role> 
</name> 

,同時仍保留了文檔的其餘部分。我嘗試了兩種方法:一種可行,但看起來很愚蠢,一種不起作用,而且看起來很愚蠢。

第一種方法

<xsl:template match="* | processing-instruction() | comment()"> 
    <xsl:copy> 
     <xsl:copy-of select="@*" copy-namespaces="no"/> 
     <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 
<xsl:template match="//name/namePart[matches(., 'Gertrude') 
        and following-sibling::namePart[@type='termsOfAddress' 
         and matches(., 'Aunt')]]"> 
    <namePart>Aunt Gertrude</namePart> 
</xsl:template> 
<xsl:template match="//name/namePart[@type='termsOfAddress' 
         and matches(., 'Aunt') 
         and preceding-sibling::namePart[matches(., 'Gertrude')]]"/> 

Seoncd方法

<xsl:template match="* | processing-instruction() | comment()"> 
    <xsl:copy> 
     <xsl:copy-of select="@*" copy-namespaces="no"/> 
     <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 
<xsl:template match="//name[descendant::namePart[matches(., 'Gertrude')] 
         and descendant::namePart[@type='termsOfAddress' 
         and matches(., 'Aunt')]]/namePart"> 
    <namePart>Aunt Gertrude</namePart> 
</xsl:template> 

所以,就像我說的,第一個作品,但有兩個單獨的模板來處理兩個要素顯得有些多餘。所以我嘗試了第二種方法給我這個:

<name type="personal" authority="local"> 
    <namePart>Aunt Gertrude</namePart> 
    <namePart>Aunt Gertrude</namePart> 
    <role> 
     <roleTerm authority="marcrelator" type="text">Correspondent</roleTerm> 
     <roleTerm authority="marcrelator" type="code">crp</roleTerm> 
    </role> 
</name> 

這不是我想要的。

有什麼辦法可以選擇兩個namePart元素並將其替換爲一個?

+0

有許多方法,但是您不會按什麼順序(排序規則)解釋應將值連接成單個字符串的方法。 –

回答

0

這種轉變

<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="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

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

    <namePart> 
     <xsl:apply-templates select="namePart"> 
     <xsl:sort select="count(@*)"/> 
     </xsl:apply-templates> 
    </namePart> 
    <xsl:apply-templates select="*[not(self::namePart)]"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="namePart"> 
    <xsl:if test="not(position()=1)"><xsl:text> </xsl:text></xsl:if> 
    <xsl:value-of select="."/> 
</xsl:template> 
</xsl:stylesheet> 

時所提供的XML文檔應用:

<name type="personal" authority="local"> 
    <namePart>Gertrude</namePart> 
    <namePart type="termsOfAddress">Aunt</namePart> 
    <role> 
    <roleTerm authority="marcrelator" type="text">Correspondent</roleTerm> 
    <roleTerm authority="marcrelator" type="code">crp</roleTerm> 
    </role> 
</name> 

產生想要的,正確的結果

<name type="personal" authority="local"> 
    <namePart>Gertrude Aunt</namePart> 
    <role> 
     <roleTerm authority="marcrelator" type="text">Correspondent</roleTerm> 
     <roleTerm authority="marcrelator" type="code">crp</roleTerm> 
    </role> 
</name> 
+0

感謝Alejandro,他在本答案的第一個版本中提醒了我一個錯誤觀念。 –

+0

不幸的是,還有其他''元素,我想複製到匹配''要求的文檔中。我正在使用的文檔實際上比我在這裏給出的文檔大很多,並且包含多個'// name/namePart'樹。 在這種情況下,我的第一個解決方案可能是最好的,因爲它確實需要我不想考慮的特定兄弟,儘管我可能會在'* | processing-instruction()|評論()'模板來說明''我不想要。 謝謝! – user1655528

+0

@ user1655528,如果您想要問題的有用答案,那麼您需要包含足夠的數據。即使在這個切割的例子中,也沒有規定字符串串聯的順序。我強烈建議您仔細考慮並提出一個新的問題,其中包含充分且具有代表性的XML文檔以及確切的通緝結果,並提供完整的,明確的要求 - 可能作爲不同用例的列表,不必猜測並提供答案,因爲他們的猜測不是你想要的。 –