XSLT:对某些节点及其特定层次结构执行复杂的转换

时间:2014-01-24 19:11:55

标签: xml xslt

我有一个转换,我正在使用它与第三方供应商集成,以强制我们的对象序列化到他们的结构。我已经完成了所有工作,除了我的大变换,我想在两个非常特定的节点和它们下面的层次结构上运行。我很难搞清楚。

这是我当前的XSLT转换:

<xsl:template match="/*|*[*]">
  <xsl:copy>
    <xsl:apply-templates select="@*"/>
    <xsl:choose>
      <xsl:when test="*[not(./*) and not(./@*)] ">
        <xsl:for-each select="*[not(./*) and not(./@*)]">
          <xsl:if test=". != ''" >
          <xsl:attribute name="{local-name(current())}">
            <xsl:value-of select="."/>
          </xsl:attribute>
          </xsl:if>
        </xsl:for-each>
      </xsl:when>
      <xsl:otherwise/>
    </xsl:choose>
    <xsl:apply-templates select="*[*]"/>
  </xsl:copy>
 </xsl:template>

  <xsl:template match="*[not(./*) and not(./@*)]"/>

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

我正在尝试在两个非常特定的节点和低于这两个节点的每个节点上执行此操作。我尝试的一切都是徒劳的。有什么想法吗?

更多信息:

示例文档:

    <Root>
        <type>Foo</type>
        <includeHTML>Yes</includeHTML>
        <SubRoot>
            <SubSubRoot>
                <ID>2.4</ID>
            </SubSubRoot>
        </SubRoot>
        <SubRoot2>
            <SubSubRoot>
                <ID>2.4</ID>
            </SubSubRoot>
        </SubRoot2>
    </Root>

现在,这就是我所得到的:

    <Root type="Foo" includeHTML="Yes">
        <SubRoot>
            <SubSubRoot ID="2.4" />
        </SubRoot>
        <SubRoot2>
            <SubSubRoot ID="2.4" />
        </SubRoot2>
    </Root>

而且,假设我只是想对SubRoot和SubRoot2进行转换,我想得到这样的结果:

    <Root>
        <type>Foo</type>
        <includeHTML>Yes</includeHTML>
        <SubRoot>
            <SubSubRoot ID="2.4" />
        </SubRoot>
        <SubRoot2>
            <SubSubRoot ID="2.4" />
        </SubRoot2>
    </Root>

现在想象一下250K XML Doc上的类似内容。我正在尝试仅在2个非常特定的节点上进行转换(最终约占文档的80%)以及它们下面的所有内容。

1 个答案:

答案 0 :(得分:0)

下面的样式表实现了所提供的示例XML的所需输出。我保持非常通用。您可以使一些匹配更具体到元素名称。

可能需要根据实际XML的深层嵌套以及您希望如何处理该内容(即知道何时转换为属性或仅向前复制)来调整。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>

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

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

    <xsl:template match="*/*/*[not(*) and not(@*)][.!='']" mode="attr">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

    <xsl:template match="*" mode="attr"/>

    <xsl:template match="*/*/*[not(*) and not(@*)][.!='']" />

</xsl:stylesheet>