XSLT中的模板更正

时间:2012-05-17 07:02:42

标签: xml xslt xslt-1.0

<To>
    <Id>SERVICE</Id>
    <Role>Commuter</Role>
</To>
<BPD>
    <OrgNo>234</OrgNo>      
</BPD>
<BON>123</BON>

我有这个输入XML,我想在其中检查//To/Id是否包含SERVICE。 如果它包含SERVICE,则应在<BPD>命名<BON>SERVICE</BON>后添加一个元素。 另外,我想检查我的输入XML是否已经包含<BON>元素,那么它的值应该是 由<Id>元素中的SERVICE替换。

我为此创建了一个模板 - &gt;

<xsl:template match="BPD">
 <xsl:choose>
   <xsl:when test="not(BON) and normalize-space(/To[Role='Commuter']/Id)='SERVICE'">
     <BON>
    <xsl:text>SERVICE</xsl:text>
     </BON>
   </xsl:when>          
   <xsl:when test="normalize-space(BON) and normalize-space(/To[Role='Commuter']/Id)='SERVICE'">
      <BON>
    <xsl:text>SERVICE</xsl:text>
      </BON>
    </xsl:when>
 </xsl:choose>
</xsl:template>

此模板正在检查是否存在。如果它不存在则会创建<BON> 元素并添加'SERVICE'作为值。 如果存在则会创建一个不需要的元素。 在情况发生时我需要纠正我的第二个。

2 个答案:

答案 0 :(得分:2)

如果你只是替换现有的<BON>,如果它存在,你应该只需要这个:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="node()|@*" name="ident">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="BPD[../To[Role='Commuter']/Id='SERVICE']">
    <xsl:call-template name="ident"/>
    <BON>SERVICE</BON>
  </xsl:template>

  <xsl:template match="BON[../To[Role='Commuter']/Id='SERVICE']"/>  

</xsl:stylesheet>

使用此输入:

<doc>
  <To>
    <Id>SERVICE</Id>
    <Role>Commuter</Role>
  </To>
  <BPD>
    <OrgNo>234</OrgNo>      
  </BPD>
  <BON>123</BON>  
</doc>

或此输入(无<BON>

<doc>
  <To>
    <Id>SERVICE</Id>
    <Role>Commuter</Role>
  </To>
  <BPD>
    <OrgNo>234</OrgNo>      
  </BPD>
</doc>

它会产生这个输出:

<doc>
   <To>
      <Id>SERVICE</Id>
      <Role>Commuter</Role>
   </To>
   <BPD>
      <OrgNo>234</OrgNo>
   </BPD>
   <BON>SERVICE</BON>
</doc>

答案 1 :(得分:0)

我认为你所说的是,如果你有一个元素 id 的'SERVICE'和角色 'Commuter'然后你要确保有一个以下 BON 元素,其值为'SERVICE'(如果它已经存在则替换现有的那个)。

这可以在不使用 xsl:choose 但是使用两个单独的匹配模板的情况下完成。首先,您可以匹配具有 BON 元素的情况,前面的元素用于“Commuter”和“SERVICE”。

<xsl:template match="BON[preceding-sibling::To[Role='Commuter'][normalize-space(Id)='SERVICE']]">

然后你可以拥有一个与 BPD 元素匹配的模板,其中根本没有 BON 元素。

这是完整的XSLT

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

   <xsl:template match="BON[preceding-sibling::To[Role='Commuter'][normalize-space(Id)='SERVICE']]" name="bon">
      <BON>SERVICE</BON>
   </xsl:template>   

   <xsl:template match="BPD[preceding-sibling::To[Role='Commuter'][normalize-space(Id)='SERVICE']][not(following-sibling::BON)]">
      <xsl:call-template name="identity" />
      <xsl:call-template name="bon" />
   </xsl:template>

   <xsl:template match="@*|node()" name="identity">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

请注意使用命名模板,以避免重复编码 BON 元素。

应用于以下XML

<Root>
   <To>
      <Id>SERVICE</Id>
      <Role>Commuter</Role>
   </To>
   <BPD>
      <OrgNo>234</OrgNo>
   </BPD>
   <BON>123</BON>
</Root>

以下是输出

<Root>
   <To>
      <Id>SERVICE</Id>
      <Role>Commuter</Role>
    </To>
    <BPD>
       <OrgNo>234</OrgNo>
    </BPD>
    <BON>SERVICE</BON>
</Root>

如果您将输入XML更改为以下内容,那么在这种情况下它也会产生相同的输出

<Root>
   <To>
      <Id>SERVICE</Id>
      <Role>Commuter</Role>
   </To>
   <BPD>
      <OrgNo>234</OrgNo>
   </BPD>
</Root>