2012-09-07 21 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文档以及确切的通缉结果,并提供完整的,明确的要求 - 可能作为不同用例的列表,不必猜测并提供答案,因为他们的猜测不是你想要的。 –