处理指令转换

时间:2010-11-12 13:55:28

标签: xslt

我想将源xml中的处理指令转换为输出中的某个标记

输入

<?xml version="1.0" encoding="utf-8"?>
<root>
    <?PI_start?> SOME TEXT <?PI_end?>
</root>

我希望输出xml像那样

<root>
    <tag> SOME TEXT </tag>
</root>

我可以这样做吗?如果是,我必须使用什么xsl进行转换?

我发现只有一种方法可以将PI转换为开始和结束标记。 PI可以包含一些内容。

输入XML

<root>
    <?PI SOME TEXT?>
</root>

XSL

<xsl:template match="processing-instruction('PI')">
    <tag><xsl:value-of select="."/></tag>
</xsl:template>

输出

<tag>SOME TEXT</tag>

但这不是我的情况

2 个答案:

答案 0 :(得分:10)

此转化

<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="processing-instruction('PI_start')">
  <tag>
   <xsl:apply-templates mode="copy" select=
       "following-sibling::node()[1][self::text()]"/>
  </tag>
 </xsl:template>

 <xsl:template match=
 "processing-instruction('PI_end')
 |
  text()[preceding-sibling::node()[1]
              [self::processing-instruction('PI_start')]]
 "/>
</xsl:stylesheet>

应用于提供的XML文档

<?xml version="1.0" encoding="utf-8"?>
<root>
    <?PI_start?> SOME TEXT <?PI_end?>
</root>

生成想要的正确结果

<root>
   <tag> SOME TEXT </tag>
</root>

请注意

  1. 使用身份规则 “按原样”复制所有节点。

  2. 我们只为那些应该以某种方式更改的节点提供了其他模板。

  3. 与第一个PI匹配的模板“几乎完成所有工作”。它创建了一个tag元素,并将模板应用于以下兄弟节点(如果它是PI) 。

  4. 我们以“复制”模式为第一个PI 的文本节点直接兄弟模板应用模板。

  5. “复制”模式未在任何地方声明,这会导致选择处理文本节点的默认模板 - 其操作只是复制文本节点。这是一种技巧,使我们无需在“复制”模式下定义模板。

  6. 我们有一个实际删除不需要的节点的空模板:第二个PI以及第一个PI的直接同级文本节点的第二个副本。

    < / LI>

    更新:OP表示他也对两个PI之间可能存在不同节点(不仅仅是文本节点)的情况感兴趣。

    这是一项更复杂的任务,这是一个解决方案:

    <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:key name="kSurrounded" match="node()"
      use="concat(
            generate-id(preceding-sibling::processing-instruction('PI_start')[1]),
            '+++',
            generate-id(following-sibling::processing-instruction('PI_end')[1])
                 )"/>
    
     <xsl:template match="node()|@*" name="identity">
         <xsl:copy>
           <xsl:apply-templates select="node()|@*"/>
         </xsl:copy>
     </xsl:template>
    
     <xsl:template match="processing-instruction('PI_start')">
      <tag>
       <xsl:apply-templates mode="copy" select=
           "key('kSurrounded',
                 concat(generate-id(),
                       '+++',
                       generate-id(following-sibling::processing-instruction('PI_end')[1])
                       )
                 )"/>
      </tag>
     </xsl:template>
    
     <xsl:template match=
     "processing-instruction('PI_end')
     |
      node()[(preceding-sibling::processing-instruction('PI_start')
             |
              preceding-sibling::processing-instruction('PI_end')
              )
               [last()][self::processing-instruction('PI_start')]
            and
             (following-sibling::processing-instruction('PI_start')
            |
              following-sibling::processing-instruction('PI_end')
              )
               [1][self::processing-instruction('PI_end')]
            ]
     "/>
    
     <xsl:template match="node()" mode="copy">
      <xsl:call-template name="identity"/>
     </xsl:template>
    </xsl:stylesheet>
    

    将以上转换应用于以下XML文档

    <root>
        <?PI_start?> <strong>Some</strong> TEXT <?PI_end?> XA <?PI_end?>
    </root>
    

    生成所需的正确输出

    <root>
        <tag>
            <strong>Some</strong> TEXT 
        </tag> XA 
    </root>
    

答案 1 :(得分:1)

我提出另一种方法来解决我的问题。我希望这是正确的

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*" />
    </xsl:copy>
</xsl:template>
<xsl:template match="processing-instruction('PI_start')">
    <xsl:text disable-output-escaping="yes"><![CDATA[<tag>]]></xsl:text>
</xsl:template>

<xsl:template match="processing-instruction('PI_end')">
    <xsl:text disable-output-escaping="yes"><![CDATA[</tag>]]></xsl:text>
</xsl:template>

<强>输入

<root>
    <?PI_start?> <strong>Some</strong> TEXT <?PI_end?> XA <?PI_end?>
</root>

产生正确的输出

<root>
    <tag> <strong>Some</strong> TEXT </tag> XA </tag>
</root>