xslt - 处理指令变换

标签 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>

但这有点不是我的情况

最佳答案

这种转变:

<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 的直接兄弟文本节点的第二个副本。

更新: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>

关于xslt - 处理指令变换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4165325/

相关文章:

date - 在 xslt 或 TIBCO BW 中将多个 dateTime 字符串解析为 dateTime 格式

xslt - xslt 下拉列表中选定的属性

xslt - xsl 引用外部 xsl 文件

xml - 使用 XSLT 重构 XML 节点

xslt - XSLT 可以插入当前日期吗?

xml - 函数 "fn:encode-for-uri"导致 XSLT 出错

java - 在 XSLT 中显示重复的标签?

xslt - 如何使用XSLT根据其依赖关系对某些XML元素进行排序?

java - 如何在 XSL 函数 'document()' (xalan-j) 中禁用 DTD 验证

java - 输入 XML 中的中文字符导致 XSLT 转换在输出 XML 中产生无效字符引用