xml - 使用 XSLT 转换特定 XML 文档

标签 xml xslt

你好

我的 XML 文档具有以下布局

<root>
  <child>
    <item type="ID">id1</item>
    <item type="TEXT">text1</item>
  </child>

  <child>
    <item type="ID"/>
    <item type="TEXT">text2</item>
  </child>

  <child>
    <item type="ID"/>
    <item type="TEXT">text3</item>
  </child>

  <child>
    <item type="ID">id2</item>
    <item type="TEXT">text4</item>
  </child>

  <child>
    <item type="ID"/>
    <item type="TEXT">text5</item>
  </child>

  ...
</root>

每当有一个 type=ID 的空 item 标签时,就意味着它与前一个同级具有相同的值。现在我想把它变成

<root>
  <child id="id1">text1text2text3</child>
  <child id="id2">text4text5</child>

  ...
</root>

我的解决方案是

<?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/">
    <root>
      <xsl:apply-templates select="//child/item[@type='ID'][text()='id1' or text()='id2']"/>
    </root>
  </xsl:template>

  <xsl:template match="child/item[text()='id1' or text()='id2']">
    <child id="{text()}">
      <xsl:value-of select="./../item[@type='TEXT']/."/>
      <xsl:apply-templates select="./../following::*[1]/item[@type='ID'][not(text()='id1' or text()='id2')]"/>
    </child>
  </xsl:template>

  <xsl:template match="child/item[not(text()='id1' or text()='id2')]">
    <xsl:value-of select="./../item[@type='TEXT']/."/>
    <xsl:apply-templates select="./../following::*[1]/item[@type='ID'][not(text()='id1' or text()='id2')]"/>
  </xsl:template>

</xsl:stylesheet>

它可以工作,但丑陋且不灵活。例如,如果我有任意 id 值,而不仅仅是 id1 和 id2,该怎么办?有人有好的建议或更好的解决方案吗?

最佳答案

这个 XSLT 1.0 样式表应该可以做到这一点:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:output indent="yes"/>

    <xsl:template match="/*">
        <root>
            <!-- visit each "child" element with a non-blank ID -->
            <xsl:for-each select="child[item[@type='ID'] != '']">
                <xsl:variable name="this-id" select="item[@type='ID']"></xsl:variable>
                <child id="{$this-id}">
                    <!-- visit this node and each following "child" element which
                        1. has a blank ID, and
                        2. whose immediate preceding non-blank ID child element is this one -->                        
                    <xsl:for-each select=".|following-sibling::child
                        [item[@type='ID'] = '']
                        [preceding-sibling::child[item[@type='ID'] != ''][1]/item[@type='ID']=$this-id]">
                        <xsl:value-of select="item[@type='TEXT']"/>
                    </xsl:for-each>
                </child>

            </xsl:for-each>
        </root>
    </xsl:template>    

</xsl:stylesheet>

关于xml - 使用 XSLT 转换特定 XML 文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6170304/

相关文章:

java - 组件扫描无法检测到接口(interface)bean?

用于动态变量名称访问的字段名 + 参数值的 XSLT 串联

php - 解析 PubMed 查询的curl结果并将其格式化为引文

c# - 在类中使用数组进行 XML 反序列化

python - 根据属性值使用 lxml 对子元素进行排序

java - 如何修改多个XML标签的值?

html - 如何在 HTML 页面中引入软分页符?

xml - XSL 将 SVG 转换为 VML

xml - 在使用XPATH的XSLT for-each方面需要帮助

xml - SVG 图像文件显示 XML 代码而不是图像