使用XPath或XSLT从XML中排除特定元素

时间:2019-08-18 11:23:51

标签: c# xslt xpath

考虑以下XML:

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>

<book category="cooking">
  <title lang="en">Everyday Italian</title>
  <author>Giada De Laurentiis</author>
  <price>30.00</price>
  <contents>jjjadLKjlkdasndlakjd...</contents>
</book>

<book category="children">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <price>29.99</price>
</book>

<book category="web" cover="paperback">
  <title lang="en">Learning XML</title>
  <author>Erik T. Ray</author>
  <price>39.95</price>
  <contents>jjjadLKjlkdasndlakjd...</contents>
</book>

</bookstore>

目标是排除“ contents”元素并获取生成的XML AS-IS。

我尝试了轴和其他运算符。但是,使用XPath似乎无法实现这一目标。如果我错了,请纠正我。

如果无法XPath隔离,以下XSLT是否可以工作?

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

  <xsl:output method="xml" omit-xml-declaration="yes" encoding="utf-8"/>

  <!-- For each element, create a new element with the same local-name (no namespace) -->
  <xsl:template match="*">
    <xsl:element name="{local-name()}">
      <xsl:copy-of select="@*"/> 
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="/">
    <xsl:apply-templates select="*[not(self::company)]"/>
  </xsl:template>

</xsl:stylesheet>

3 个答案:

答案 0 :(得分:2)

只需将XSLT的第二个模板更改为空模板:

<xsl:template match="contents" />

此外,如果您想要保留名称空间(以保留XML的其余“ AS-IS”),则可以简单地使用身份模板:

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

答案 1 :(得分:0)

如果要排除contents元素,则需要使用:

<xsl:apply-templates select="*[not(self::contents)]"/>

代替您的

<xsl:apply-templates select="*[not(self::company)]"/>

此外,由于contentsbook的子代,因此您需要在与book元素而不是/根节点匹配的模板中执行此操作。而且您还想复制父book及其属性-这样就可以了:

<xsl:template match="book">
  <xsl:copy>
    <xsl:apply-templates select="@* | *[not(self::contents)]"/>
  </xsl:copy>
</xsl:template>

或-如果您需要删除源名称空间(您的示例没有该名称空间?):

<xsl:template match="book">
  <xsl:element name="{local-name()}">
    <xsl:apply-templates select="@* | *[not(self::contents)]"/>
  </xsl:element>
</xsl:template>

答案 2 :(得分:-3)

使用Xml Linq:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            List<XElement> contents = doc.Descendants("contents").ToList();
            for (int i = contents.Count - 1; i >= 0; i--)
            {
                contents[i].Remove();
            }
        }
    }
}