如何使用C#将带有属性长度的xml空元素标记转换为start-tag和end-tag?

时间:2012-06-18 16:05:24

标签: c# xml xslt

我想转换属性长度为

的xml空元素标签
<tag length=”3”/>xxxxxxx

进入开始标记和结束标记

<tag>xxx</tag>xxxx

使用C#或XSLT

你有个主意吗?

来自:

    <comment>
      <opinion id="tag_1" length="93"/>
      Un bon traiteur Findi Traiteur propose un choix de 
      <topicInstance id="tag_2" length="13"/>
      pâtes cuites à la minute et d'
      <topicInstance id="tag_3" length="9"/>
      antipasti.
    </comment>

致:

    <comment>
      <opinion id="tag_1">
      Un bon traiteur Findi Traiteur propose un choix de 
      <topicInstance id="tag_2">
      pâtes cuites</topicInstance> à la minute et d'
      <topicInstance id="tag_3">
      antipasti</topicInstance>.
      </opinion>
    </comment>

2 个答案:

答案 0 :(得分:1)

以下是实现所需处理的完整而简单的转换

<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="*[@length]">
  <xsl:variable name="vFollowingText" select=
  "normalize-space(following-sibling::text()[1])"/>

  <xsl:copy>
   <xsl:apply-templates select="@*[not(name()='length')]"/>
   <xsl:value-of select="substring($vFollowingText, 1, @length)"/>
   <xsl:apply-templates/>
  </xsl:copy>
  <xsl:value-of select="substring($vFollowingText, @length+1)"/>
 </xsl:template>

 <xsl:template match="text()[preceding-sibling::*[1][@length]]"/>
</xsl:stylesheet>

在提供的XML文档上应用此转换时:

<comment>
    <opinion id="tag_1" length="93"/>
    Un bon traiteur Findi Traiteur propose un choix de        
    <topicInstance id="tag_2" length="13"/>
    pâtes cuites à la minute et d'       
    <topicInstance id="tag_3" length="9"/>
    antipasti.     
</comment>

产生了想要的正确结果

<comment>
  <opinion id="tag_1">Un bon traiteur Findi Traiteur propose un choix de</opinion><topicInstance id="tag_2">pâtes cuites </topicInstance>à la minute et d'<topicInstance id="tag_3">antipasti</topicInstance>.</comment>

<强>更新

根据@enguerran的评论,<opinion>应该包含其余的内容,这里有一个转换:

<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="*[@length]" mode="following">
  <xsl:variable name="vFollowingText" select=
  "normalize-space(following-sibling::text()[1])"/>

  <xsl:copy>
   <xsl:apply-templates select="@*[not(name()='length')]"/>
   <xsl:value-of select="substring($vFollowingText, 1, @length)"/>
   <xsl:apply-templates/>
  </xsl:copy>
  <xsl:value-of select="substring($vFollowingText, @length+1)"/>
 </xsl:template>

 <xsl:template match="*[@length and not(preceding-sibling::*/@length)]">
  <xsl:copy>
   <xsl:apply-templates select="@*[not(name()='length')]"/>
   <xsl:apply-templates select="node()"/>
   <xsl:apply-templates mode="following" select=
    "following-sibling::text()[1] |following-sibling::*" />
  </xsl:copy>
 </xsl:template>
 <xsl:template match="*[preceding-sibling::*[1][@length]] | text()"/>
</xsl:stylesheet>

在提供的XML文档(上面)上应用此转换时,会生成所需的正确结果

<comment>
<opinion id="tag_1">
      Un bon traiteur Findi Traiteur propose un choix de
      <topicInstance id="tag_2">pâtes cuites </topicInstance>à la minute et d'<topicInstance id="tag_3">antipasti</topicInstance>.</opinion>
</comment>

答案 1 :(得分:0)

这可能在某种程度上满足您的要求:

<xsl:template match="comment/opinion|comment/topicInstance">
    <xsl:copy>
        <!-- copy attributes except for "length" -->
        <xsl:for-each select="@*[local-name() != 'length']">
            <xsl:copy/>
        </xsl:for-each>
        <!-- include characters from the following text node -->
        <xsl:value-of select="substring(following-sibling::text()[1], 1, @length)"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="comment/text()">
    <xsl:variable name="previous" select="preceding-sibling::node()[1]"/>
    <!-- strip characters that have been inserted in the previous node -->
    <xsl:value-of select="substring(*, $previous/@length + 1)"/>
</xsl:template>

它不会涵盖所有情况,您需要添加一些检查(例如检查前一个节点是否存在等)。