使用XSLT删除XML中的父节点

时间:2013-10-29 11:04:39

标签: xml xslt xslt-2.0

我需要帮助,使用XSLT从给定的XML中删除父节点。

<?xml version="1.0" encoding="UTF-8"?>
<Report xmlns="OpenProblems2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="OpenProblems2" Name="OpenProblems2">
   <Hello>
      <NewDataSet>
         <Table>
            <a>1832874</a>
            <b>HUME-9063</b>
            <c>not informed</c>
         </Table>
         <Table>
            <a>1832874</a>
            <b>HUME-9063</b>
            <c>not informed</c>
         </Table>
      </NewDataSet>
   </Hello>
</Report>

输出应该看起来像 -

<NewDataSet>
<Table>
  <a>1832874</a> 
  <b>HUME-9063</b> 
  <c>not informed</c>
</Table>
<Table>
  <a>1832874</a> 
  <b>HUME-9063</b> 
  <c>not informed</c>
</Table>
</NewDataSet>

XSLT应删除Report,Hello&amp; NewDataset元素。请...我们将非常感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

使用XSLT对XML文件进行小的更改的标准方法是定义标识模板,它将输入到输出的所有内容按原样复制,除非被更具体的模板覆盖:< / p>

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

然后提供特定模板以匹配您要更改的内容。在这种情况下,如果您知道将始终存在一个第三级元素(NewDataSet),那么您可以使用

跳过前两个级别的外包装元素
<xsl:template match="/">
  <xsl:apply-templates select="*/*/*" />
</xsl:template>

这两个模板一起产生这样的输出

<NewDataSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns="OpenProblems2">
<Table>
  <a>1832874</a> 
  <b>HUME-9063</b> 
  <c>not informed</c>
</Table>
<Table>
  <a>1832874</a> 
  <b>HUME-9063</b> 
  <c>not informed</c>
</Table>
</NewDataSet>

如果您还想删除所有名称空间,则需要添加第三个模板:

<xsl:template match="*">
  <xsl:element name="{local-name()}">
    <xsl:apply-templates select="@*|node()" />
  </xsl:element>
</xsl:template>

获取任何(或没有)命名空间中的任何元素,并将其替换为具有相同本地名称但在命名空间中 not 的新元素。

答案 1 :(得分:1)

如果你想保留命名空间,那么你只需要

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

    <xsl:template match="/">
        <xsl:copy-of select="o:NewDataSet"/>
    </xsl:template>

</xsl:stylesheet>

答案 2 :(得分:0)

这种要求最好使用身份模板处理。身份模板将允许您不改变地传递大部分XML,然后仅处理必要的部分。一个简单的身份看起来像:

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

这匹配所有属性,注释,元素等,并将它们复制到输出中。任何更具体的匹配都将优先。

您的示例输出实际上并未删除NewDataSet元素,因此我也没有。如果要删除它,请将其添加到下面的模板中(但请记住它会使输出格式错误)

<xsl:template match="Hello|Report">
    <xsl:apply-templates/>
</xsl:template>

此模板匹配HelloReport元素,并通过简单地将模板应用于其子元素而不将实际节点复制到输出来处理它们。

所以,样式表如:

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

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

    <xsl:template match="Hello|Report">
        <xsl:apply-templates/>
    </xsl:template>

</xsl:stylesheet>

将获取您的样本输入并生成您的样本输出。正如@ ian-roberts指出的那样,如果你真的想要删除命名空间,你也需要处理它。