如何重构XSLT模板以使其可重用

时间:2013-09-02 07:45:55

标签: xml xslt refactoring

我有以下模板,创建一个xml。一个模板中有多个类似的代码块。根据父元素名称,只有一个元素值。我对使用if test而不仅仅是template match的疑问也是一个不完美的想法?但那怎么样?:

   <xsl:template match="Adresse">
    <!-- TelefonG  -> "Telefon Geschäftlich" (ID = 1) -->
    <xsl:if test="TelefonG != '' or TelefonGZus != ''">
      <xsl:if test="PersonGuid != ''">
        <xsl:element name="AdrKontakt">
          <KontaktGuid>
            <xsl:value-of select="commonFunctions:createGuid()"/>
          </KontaktGuid>
          <PersonGuid>
            <xsl:value-of select="commonFunctions:convertGuid(PersonGuid)"/>
          </PersonGuid>
          <InfoText>
            <xsl:value-of select="commonFunctions:toHtmlEntities(TelefonG)"/>
          </InfoText>
          <Kommentar>
            <xsl:value-of select="commonFunctions:toHtmlEntities(TelefonGZus)"/>
          </Kommentar>
          <xsl:element name="KontaktTypID">1</xsl:element>
          <xsl:the-same-crap/>
        </xsl:element>
      </xsl:if>
    </xsl:if>

        <!-- TelefonP   -> "Telefon Privat" (ID = 2) -->
        <xsl:if test="TelefonP != '' or TelefonPZus != ''">
          <xsl:if test="PersonGuid != ''">
            <xsl:element name="AdrKontakt">
              <xsl:the-same-crap/>
              <xsl:element name="KontaktTypID">1</xsl:element>
              <xsl:the-same-crap/>
            </xsl:element>
          </xsl:if>
        </xsl:if>

        <!-- TelMobil -> "Telefon Mobil" (ID = 3) -->
        <xsl:if test="TelMobil != '' or TelMobilZus != ''">
          <xsl:if test="PersonGuid != ''">
            <xsl:element name="AdrKontakt">
              <xsl:the-same-crap/>
              <xsl:element name="KontaktTypID">3</xsl:element>
              <xsl:the-same-crap/>
            </xsl:element>
          </xsl:if>
        </xsl:if>

        <xsl:and-so-on/>

输入xml如下所示:

...
<Adresse>
  <PersonGuid>THEGUID01234567890</PersonGuid>
  <TelefonP>0878938493</TelefonP>
  <TelefonPZus>Some text about this number</TelefonPZus>
  <TelefonG>9309340934</TelefonG>
  <TelefonGZus>First class customer.</TelefnoGZus>
  <TelefonM>090923409</TelefonM>
  <TelefonMZus>Mobile because not always in office.</TelefonMZus> 
  <Email>abuse@bad.com</Email>
  <EmailZus>suspect</EmailZus>
  <!-- and so one -->
</Adresse>
<Adresse>
  <Email>bla@foo.bar</Email>
  <TelefonM>0298309283</TelefonM>
<Adresse>
...

你如何重构它来写同样的废话?有些开关盒吗?例如。 TelefonP =&gt; 1; TelMobil =&gt; 3等 提前致谢

1 个答案:

答案 0 :(得分:1)

首先,除了当前的模板之外,我还要添加第二个模板,忽略没有 PersonGuid 地址元素

<xsl:template match="Adresse[PersonGuid = '']" />

这是因为在所有三个模板中,您只输出有 PersonGuid 的新元素。这将简化模板中的代码,因为您可以在此条件下删除相应的 xsl:if

请注意,在这种情况下,XSLT将始终优先考虑更具体的模板。

至于重新分解代码,我认为你可以在这里使用 xsl:choose ,但是在你输出的 AdrKontakt 中定位。

<xsl:template match="Adresse">
 <AdrKontakt>
    <xsl:the-same-crap/>
    <KontaktTypID>
       <xsl:choose>
          <xsl:when test="TelefonG != '' or TelefonGZus != ''">1</xsl:when>
          <xsl:when test="TelefonP != '' or TelefonPZus != ''">1</xsl:when>
          <xsl:when test="TelMobil != '' or TelMobilZus != ''">3</xsl:when>
       <xsl:choose>
    </KontaktTypID>
    <xsl:the-same-crap/>
 </AdrKontakt>
</xsl:tempalte>

<xsl:template match="Adresse[PersonGuid = '']" />

请注意,没有必要使用 xsl:element 在这里输出新元素,只需直接输出元素。

编辑:如果您需要输出多个 AdrKontakt ,那么您调用可能会使用带参数的命名模板来包含重复的代码:

命名模板如下所示:

<xsl:template name="AdrKontakt">
 <xsl:param name="KontaktTypID" />
 <AdrKontakt>
    <xsl:the-same-crap/>
    <KontaktTypID>
       <xsl:value-of select="$KontaktTypID" />
    </KontaktTypID>
    <xsl:the-same-crap/>
 </AdrKontakt>
</xsl:tempalte>

打电话给你,你会这样做:

<xsl:template match="Adresse">
  <xsl:if test="TelefonG != '' or TelefonGZus != ''">
      <xsl:call-template name="AdrKontakt">
          <xsl:with-param name="KontaktTypID" select="'1'" />
      </xsl:call-template>
  </xsl:if>
  <xsl:if test="TelefonP != '' or TelefonPZus != ''">
     ...

等等你的其他条件。您将无法消除 xsl:lf ,但您重复的代码现在只会出现在一个地方。

请注意,在指定模板 AdrKontakt 中,您当前的上下文仍然是 Adresse 元素,因此您仍然可以输出当前的其他元素:

<xsl:template name="AdrKontakt">
 <xsl:param name="KontaktTypID" />
 <AdrKontakt>
    <InfoText>
       <xsl:value-of select="commonFunctions:toHtmlEntities(TelefonG)"/>
    </InfoText>
    <KontaktTypID>
       <xsl:value-of select="$KontaktTypID" />
    </KontaktTypID>
 </AdrKontakt>
</xsl:tempalte>