通用XSLT 1.0在某些特定节点路径上转换XML

时间:2015-03-30 08:52:32

标签: xml xslt

我正在尝试将XML文件转换为带有一些选定节点的规范化XML。 我将节点名称的路径保存在一个变量中,如下所示:

  <xsl:variable name="nodePath">
    <path>class/id</path>
    <path>class/title</path>
    <path>class/description_url</path>
    <path>class/duration</path>
  </xsl:variable> 

XML示例数据:

<?xml version="1.0" encoding="utf-8" ?>
<table>
  <other_node>Ignore</other_node>
  <class>
    <id>Test Data</id>
    <title>Testing</title>
    <description_url>Test Data</description_url>
    <duration>2</duration>
  </class>
  <class>
    <id>Test Data</id>
    <title>Testing</title>
    <description_url>Test Data</description_url>
    <duration>2</duration>
    <other_node>Ignore</other_node>
  </class>
  <class>
    <id>Test Data</id>
    <title>Testing</title>
    <description_url>Test Data</description_url>
    <duration>2</duration>
  </class>
</table>

输出:

<rows>
  <row>
    <id>Test Data</id>
    <title>Testing</title>
    <description_url>Test Data</description_url>
    <duration>2</duration>
  </row>
  <row>
    <id>Test Data</id>
    <title>Testing</title>
    <description_url>Test Data</description_url>
    <duration>2</duration>
  </row>
  <row>
    <id>Test Data</id>
    <title>Testing</title>
    <description_url>Test Data</description_url>
    <duration>2</duration>
  </row>
</rows>

请帮忙。提前谢谢。

1 个答案:

答案 0 :(得分:1)

我不认为你提出这个问题时会解决问题,但你可以做类似的事情。有问题的是你没有真正列出你想要保留的所有元素的路径,例如你仍然需要tableclass,即使它们没有在变量中列出,也是如此寻找文本(文本也是一个节点)。

然后您的变量包含相对路径,并且不清楚它们应用于输入树中的哪个级别。解决此问题的方法是使用level属性指示表达式的级别。

从变量中读取路径表达式在XSLT 1.0中引入了两个难点:

  • 迭代xsl:variable内的元素,即使用它作为结果树片段,在标准XSLT 1.0中是不可能的。使用exsl:node-set()
  • 标准XSLT 1.0无法将字符串计算为XPath表达式。使用dyn:evaluate()

<强>样式表

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:dyn="http://exslt.org/dynamic"
    xmlns:exsl="http://exslt.org/common"
    extension-element-prefixes="dyn exsl">

    <xsl:output method="xml" indent="yes"/>

    <xsl:variable name="nodePath">
        <path level="1">class</path>
        <path level="2">id</path>
        <path level="2">title</path>
        <path level="2">description_url</path>
        <path level="2">duration</path>
    </xsl:variable> 

    <xsl:template match="/table">
        <xsl:variable name="context" select="."/>
        <xsl:copy>
            <xsl:for-each select="exsl:node-set($nodePath)/*[@level = '1']">
                <xsl:apply-templates select="dyn:evaluate(concat('$context/',.))"/>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/table/*">
        <xsl:variable name="context" select="."/>
        <xsl:copy>
            <xsl:for-each select="exsl:node-set($nodePath)/*[@level = '2']">
                <xsl:apply-templates select="dyn:evaluate(concat('$context/',.))"/>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/table/*/*">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

XML输出

<?xml version="1.0" encoding="UTF-8"?>
<table>
<class>
<id>Test Data</id>
<title>Testing</title>
<description_url>Test Data</description_url>
<duration>2</duration>
</class>
<class>
<id>Test Data</id>
<title>Testing</title>
<description_url>Test Data</description_url>
<duration>2</duration>
</class>
<class>
<id>Test Data</id>
<title>Testing</title>
<description_url>Test Data</description_url>
<duration>2</duration>
</class>
</table>