写混合节点(标记+文本)仅替换特定节点

时间:2015-04-02 15:07:11

标签: html xslt xslt-1.0 xsl-fo jaxp

我在子节点之间有一个循环 我可以说一句话:阻止比另一个词:

<mynode>
Hi ok 
<fo:block>
hi ok fo block
< /fo:block>
maybe another text node here...
</mynode>

我必须将<fo:block>替换为<div>,但我必须将文本保留在相同的位置(如果存在,可以在fo:block之前和之后)

我尝试这段代码但是(假设循环子(*)节点):

<xsl:for-each select="/mynode">
  <xsl:if test="text()"><xsl:value-of select="text()"/></xsl:if>
  <xsl:for-each select="child::*"> 
    <!--for every child node of mynode-->
    <xsl:choose>
      <xsl:when test="normalize-space(local-name()) 
                      = normalize-space('block')"> 
        <xsl:call-template name="fo-block">
          <xsl:with-param .../>
        </xsl:call-template>
      </xsl:when>
    <xsl:otherwise>
      <xsl:if test="text()"><xsl:value-of select="text()"/></xsl:if>
    </xsl:otherwise>
  </xsl:choose>
</xsl:for-each>
</xsl:for-each>

如果test = text()所以节点包含文本然后显示文本,否则我得到节点的名称并测试if是否为块:如果是,我调用特定模板,否则测试是否包含文本。

现在似乎工作..那么,我的范围可能是正确的选择/代码吗?

谢谢!

拉​​吉

2 个答案:

答案 0 :(得分:0)

乍一看出现的问题包括:

  • 你的内部for-each循环遍历child::*,它将匹配每个元素子元素;它不会匹配任何其他子项(文本节点,注释,处理指令)。我认为你的意思是child::node()

  • 您对块元素("normalize-space(local-name()) = normalize-space('block')")的测试是名称空间遗忘,因此它不必要地脆弱。对normalize-space()的调用是没有意义的,因为local-name()永远不会返回包含空格的任何字符串,并且文字字符串&#39; block&#39;不包含任何空格。

    更短,更可靠的测试是test="self::fo:block"

  • 你说

    Seems to work for now..
    

    如果您的测试显示此代码有效,那么您的测试并没有给您带来尽可能好的效果。

您描述的处理部分似乎相当于:将fo:block元素更改为div;让其他一切都一样。处理此类转换的最简单方法是编写身份转换,然后添加更具体的规则来捕获需要更改的内容。例如:

<xsl:template match="fo:block">
  <div>
    <xsl:apply-templates select="@*|node()"/>
  </div>
</xsl:template>

<!--* other non-identity processing goes here ... *-->

<!--* What we don't have specific rules for gets handled
    * by the following template and the default templates,
    * which together perform an identity transform. *-->

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

答案 1 :(得分:0)

M。,

您的架构和响应非常有用

我增加了我的fo:block translation的复杂性:如果im在表中(在fo:cell parent中)我认为属性被html替换我使用div,否则(任何地方)p ..所以,我做了这些修改,希望你同意:

<xsl:template match="fo:block">

<xsl:choose>
<xsl:when test="parent::fo:table-cell">
<div>
    <xsl:apply-templates select="node()"/>
 </div> 
 </xsl:when>
 <xsl:otherwise>
    <xsl:if test="@space-before"> <!--  distance before is rep. by br -->
        <xsl:call-template name="count-br"> <!-- write a br tag for each unit -->
            <xsl:with-param name="howmuch"><xsl:value-of select="substring-before(normalize-space(@space-before),'cm')"/></xsl:with-param>  
        </xsl:call-template>
    </xsl:if>
 <p>
    <xsl:if test="@font-size">
        <xsl:attribute name="font-size"><xsl:value-of select="@font-size"/></xsl:attribute>
    </xsl:if>
    <xsl:if test="@text-align">
        <xsl:attribute name="text-align"><xsl:value-of select="@text-align"/></xsl:attribute>
    </xsl:if>
    <xsl:if test="@font-family">
        <xsl:attribute name="font-family"><xsl:value-of select="@font-family"/></xsl:attribute>
    </xsl:if>
    <xsl:apply-templates select="node()"/>        
 </p>
 </xsl:otherwise>
 </xsl:choose>
 </xsl:template>