如果节点有时是不同的元素,我如何编号

时间:2015-01-23 17:28:03

标签: xml xslt xpath

我需要使用xsl转换对包含数据(xml)的节点进行编号。编号的节点可能具有不同标签名称的元素。 我一直在寻找解决方案,但我找不到合适的编号方式。

以下是输入文件示例:

       <Contract>
        <Parametr1>
            <Interposes>
                   <Accomplice>
                    <Person>
                        <Name>John</Name>
                           <Surname>Person1</Surname>
                    </Person>
                   </Accomplice>
                <Representative>
                    <Name>George</Name>
                    <Surname>Person2</Surname>
                   </Representative>
            </Interposes>
            <Interposes>
                <Accomplice>
                    <Person>
                        <Name>Andy</Name>
                        <Surname>Person3</Surname>
                    </Person>
                </Accomplice>
            </Interposes>
            <Interposes>
                <Accomplice>
                    <Firm>
                        <FirmName>VeloDrom</FirmName>
                        <Description>Description</Description>
                    </Firm>
                </Accomplice>
                <Representative>
                    <Name>Agnes</Name>
                    <Surname>Person4</Surname>
                </Representative>
                <Representative>
                    <Name>Michael</Name>
                    <Surname>Person5</Surname>
                </Representative>
            </Interposes>
        </Parametr1>
       </Contract>

正确的结果应如下所示:

  
      
  1. 代表某人的George Person2:John Person1
  2.   
  3. Andy Person3
  4.   
  5. 代表公司的Agnes Person4:VeloDrom描述
  6.   
  7. 代表公司的Michael Person5:VeloDrom描述
  8.   

我尝试解决(不成功):

      <xsl:template match="Contract">
        <xsl:apply-templates select="Parametr1"/>
      </xsl:template>


      <xsl:template match="Parametr1">

          <xsl:apply-templates select="Interposes/Accomplice/Person"/>

          <xsl:apply-templates select="Interposes/Representative"/>

      </xsl:template>


      <xsl:template match="Interposes/Accomplice/Person | Interposes/Representative">
          <xsl:number format="1. " count="Interposes/Accomplice/Person | Interposes/Representative"/>
        <xsl:choose>
          <xsl:when test="count(./Interposes/Representative)=0">
            <xsl:apply-templates select="Interposes/Accomplice/Person"/>
          </xsl:when>
          <xsl:when test="count(./Interposes/Representative) &gt; 0">
            <xsl:text> </xsl:text>
              <xsl:value-of select="./Name"/><xsl:text> </xsl:text>
            <xsl:value-of select="./Surname"/>
            <xsl:if test="count(../Representative) &gt; 0">
              <xsl:if test="../Accomplice/Person">
                <xsl:text>, representing a person: </xsl:text>
                <xsl:value-of select="../Accomplice/Person/Name"/><xsl:text> </xsl:text>
                   <xsl:value-of select="../Accomplice/Person/Surname"/>
                 </xsl:if>
                 <xsl:if test="../Accomplice/Firm">
                   <xsl:text>, representing a firm: </xsl:text>
                   <xsl:value-of select="../Accomplice/Firm/FirmName"/><xsl:text> </xsl:text>
                   <xsl:value-of select="../Accomplice/Firm/Description"/>
                 </xsl:if>
               </xsl:if>
             </xsl:when>
           </xsl:choose>
       </xsl:template>

如何正确地做到这一点?

1 个答案:

答案 0 :(得分:1)

首先,在匹配Parametr1的模板中,您应该将两个xsl:apply-templates合并为一个。

<xsl:apply-templates select="Interposes[not(Representative)]/Accomplice
                             |Interposes/Representative"/>

在这种情况下,我稍作修改,选择Accomplice元素,也只选择那些没有Representative

的元素

执行此操作后,您可以使用position()功能获取该号码。这将返回您刚刚选择的各个节点的位置(按文档顺序)。

为了保持整洁,我会为AccompliceRepresentative设置单独的模板....

<xsl:template match="Accomplice">
   <xsl:value-of select="position()"/>
   <xsl:text>. </xsl:text>
   <!-- Select either Person or Firm -->

<xsl:template match="Representative">
   <xsl:value-of select="position()"/>
   <xsl:text>. </xsl:text>
   <xsl:value-of select="concat(Name, ' ', Surname)"/>

请注意,此处不需要匹配中元素名称的完整路径。另请注意,在这种情况下,您不需要Accomplice上的条件,因为它将选择条件为真的元素。

现在应该变得更加直截了当,Representative模板中唯一的额外工作是选择他们代表公司还是个人

  <xsl:choose>
     <xsl:when test="../Accomplice/Person">
        <xsl:text>, representing a person: </xsl:text>
     </xsl:when>
     <xsl:otherwise>
        <xsl:text>, representing a firm: </xsl:text>
     </xsl:otherwise>
  </xsl:choose>

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="text"/>

   <xsl:template match="Parametr1">
      <xsl:apply-templates select="Interposes[not(Representative)]/Accomplice|Interposes/Representative"/>
   </xsl:template>

   <xsl:template match="Accomplice">
      <xsl:value-of select="position()"/>
      <xsl:text>. </xsl:text>
      <!-- Select either Person or Firm -->
      <xsl:apply-templates select="*"/>
   </xsl:template>

   <xsl:template match="Representative">
      <xsl:value-of select="position()"/>
      <xsl:text>. </xsl:text>
      <xsl:value-of select="concat(Name, ' ', Surname)"/>
      <xsl:choose>
         <xsl:when test="../Accomplice/Person">
            <xsl:text>, representing a person: </xsl:text>
         </xsl:when>
         <xsl:otherwise>
            <xsl:text>, representing a firm: </xsl:text>
         </xsl:otherwise>
      </xsl:choose>
      <xsl:apply-templates select="../Accomplice/*"/>
   </xsl:template>

   <xsl:template match="Person">
      <xsl:value-of select="concat(Name, ' ', Surname)"/>
      <xsl:value-of select="'&#10;'"/>
   </xsl:template>

   <xsl:template match="Firm">
      <xsl:value-of select="concat(FirmName, ' ', Description)"/>
      <xsl:value-of select="'&#10;'"/>
   </xsl:template>
</xsl:stylesheet>

请注意使用与PersonFirm匹配的模板,以允许它们在AccompliceRepresentative模板中使用。