XSL:用一个替换两个兄弟元素

时间:2012-09-07 19:10:47

标签: xslt-2.0 xpath-2.0

我正在尝试替换此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>

使用此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元素并用一个替换它?

1 个答案:

答案 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>