使用不同级别的嵌套重复元素类型修剪XML

时间:2016-08-09 19:30:46

标签: xml xpath xslt-1.0

我需要维护XML文档的结构,但只需删除所有不具有指定ID的detail元素(在以下示例中,我只想保留id="1"。代码示例只有三个级别(A,B,C),但是假设代码模式可以无限期地继续。我是否可以在XML上使用xpath来修剪掉与id不匹配的所有detail元素保持树?

输入

<A>
    <B>
        <C>
            <details id="1">...</details>
            <details id="2">...</details>
        </C>
        <C>
            <details id="1">...</details>
            <details id="2">...</details>
        </C>
        <details id="1">...</details>
        <details id="2">...</details>
    </B>
    <B>
        <C>
            <details id="1">...</details>
            <details id="2">...</details>
        </C>
        <C>
            <details id="1">...</details>
            <details id="2">...</details>
        </C>
        <details id="1">...</details>
        <details id="2">...</details>
    </B>
    <details id="1">...</details>
    <details id="2">...</details>
</A>

所需输出

<A>
    <B>
        <C>
            <details id="1">...</details>
        </C>
        <C>
            <details id="1">...</details>
        </C>
        <details id="1">...</details>
    </B>
    <B>
        <C>
            <details id="1">...</details>
        </C>
        <C>
            <details id="1">...</details>
        </C>
        <details id="1">...</details>
    </B>
    <details id="1">...</details>
</A>

2 个答案:

答案 0 :(得分:1)

怎么样:

XSLT 1.0

namespace ClipboardAssistant.Properties {


    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {

        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));

        public static Settings Default {
            get {
                return defaultInstance;
            }
        }

        [global::System.Configuration.UserScopedSettingAttribute()]
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        public global::System.Collections.ObjectModel.ObservableCollection<ClipboardAssistant.Models.Copyable> Copyables {
            get {
                return ((global::System.Collections.ObjectModel.ObservableCollection<ClipboardAssistant.Models.Copyable>)(this["Copyables"]));
            }
            set {
                this["Copyables"] = value;
            }
        }
    }
}

请注意,这假设已移除的<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:strip-space elements="*"/> <!-- identity transform --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="details[not(@id='1')]"/> </xsl:stylesheet> 元素没有您要保留的任何子项。

答案 1 :(得分:0)

使用正确的XML解析器

非常简单

此程序使用XML::Twig。它只是解析XML文件,使用XPath表达式查找id不是1的所有details元素并删除它们,然后打印结果

输入XML文件需要作为命令行上的参数

use strict;
use warnings 'all';

use XML::Twig;

my ($xml_file) = @ARGV;

my $twig = XML::Twig->new;
$twig->parsefile($xml_file);

$_->delete for $twig->findnodes('//details[@id != 1]');

$twig->set_pretty_print('indented');
$twig->print;

输出

<A>
  <B>
    <C>
      <details id="1">...</details>
    </C>
    <C>
      <details id="1">...</details>
    </C>
    <details id="1">...</details>
  </B>
  <B>
    <C>
      <details id="1">...</details>
    </C>
    <C>
      <details id="1">...</details>
    </C>
    <details id="1">...</details>
  </B>
  <details id="1">...</details>
</A>