尝试使用XPath来过滤XML [英] Trying to Filter XML using XPath

查看:176
本文介绍了尝试使用XPath来过滤XML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想筛选使用XPath的XML文件。我正在使用XPath绝对过滤到我想要的数据,但我只是不知道如何全面过滤文件。



下面的示例XML文件:

 <田> 
<字段名='F'>
<字段名='0'>< VALUE> F.0东西< /值>< /场>
<字段名='1'>< VALUE> F.1的东西与LT; /值>< /场>
<字段名='2'>< VALUE> F.2东西< /值>< /场>
< /场>
<字段名='B'>
<字段名='0'>< VALUE> B.0东西< /值>< /场>
<字段名='1'>< VALUE> B.1东西< /值>< /场>
<字段名='2'>< VALUE> B.2东西与LT; /值>< /场>
<字段名='3'>< VALUE> B.3东西< /值>< /场>
< /场>
< /田>

下面是所需的输出:

 <&领域GT; 
<字段名='F'>
<字段名='1'>< VALUE> F.1的东西与LT; /值>< /场>
<字段名='2'>< VALUE> F.2东西< /值>< /场>
< /场>
<字段名='B'>
<字段名='3'>< VALUE> B.3东西< /值>< /场>
< /场>
< /田>



该解决方案并不一定必须由XPath的解决,但由于这是一个.NET应用程序, .NET的API,将不胜感激!下面的代码可以剪切并粘贴到 LINQPad 没有编辑看到我想要做的。

  VAR DOC = XDocument.Parse(@
<田>
<字段名= 'F'>
<字段名='0'><价值> F.0东西< /值>< /场>
<字段名='1'> <价值> F.1的东西与LT; /值>< /场>
<字段名='2'><价值> F.2东西< /值>< /场>
< /场>
<字段名='b'>
<字段名='0'><价值> B.0东西< /值>< /场>
<字段名='1'><价值> B.1东西< /值>< /场>
<字段名='2'><价值> ; B.2东西< /值>< /场>
<字段名='3'><价值> B.3东西< /值>< /场>
< ; /场>
< /田>);
doc.Dump(原始XML);

VAR的XPath =//场/场[@名称='F'] /场[@名称='1'或@名称='2'] | //场/场[@名称='B'] /场[@名称='3'];
doc.XPathSelectElements(的XPath)使用.dump(XPath的组合);

VAR所需= XDocument.Parse(@
<田>
<字段名='F'>
<字段名='1 '><价值> F.1的东西与LT; /值>< /场>
<字段名='2'><价值> F.2东西< /值>< /场> ;
< /场>
<字段名='b'>
<字段名='3'><价值> B.3东西< /值> < /场>
< /场>
< /田>);
desired.Dump(所需的过滤XML);



编辑:我完全错过了XML变换 - 谢谢你的解决方案!这里是你可以粘贴到LINQPad看到它的工作解决方案:

  VAR filterString = @@ NAME =F ] /场[@name =0] |场[@name =B] /场[不(@name =3); 
VAR xslFmt = @
<的xsl:样式版本='1.0'
的xmlns:XSL =HTTP://www.w3.org/1999/XSL/Transform'>
< XSL:输出中省略的XML声明='是'缩进='是'/>

<的xsl:模板匹配='节点()| @ *'> ;
< XSL:复制>
< XSL:申请模板选择=节点()| @ */>
< / XSL:复制>
< / XSL:模板>

<的xsl:模板匹配=
'字段[{0}]
'/>
< / XSL:样式表>中;
VAR xslMarkup =的String.Format(xslFmt,filterString);

VAR xmlTree = XDocument.Parse(@
<田>
<字段名='F'>
<字段名='0 '><价值> F.0东西< /值>< /场>
<字段名='1'><价值> F.1的东西与LT; /值>< /场> ;
<字段名='2'><价值> F.2东西< /值>< /场>
< /场>
<字段名= 'b'>
<字段名='0'><价值> B.0东西< /值>< /场>
<字段名='1'> <价值> B.1东西< /值>< /场>
<字段名='2'><价值> B.2东西与LT; /值>< /场>
<字段名='3'><价值> B.3东西< /值>< /场>
< /场>
< /田>);
xmlTree.Dump(原始XML);

//代码从MSDN:http://msdn.microsoft.com/en-us/library/bb675186.aspx
变种NEWTREE =新的XDocument();
使用(VAR作家= newTree.CreateWriter()){
//加载样式表。
变种XSLT =新XslCompiledTransform();
xslt.Load(XmlReader.Create(新StringReader(xslMarkup)));

//执行变换和结果输出到一个作家。
xslt.Transform(xmlTree.CreateReader(),作家);
}

newTree.Dump(转化XML);


解决方案

XPath是一种查询语言,它可以不被用于产生一个修改的XML文档



这是特别为这样的转换而设计的技术被称为的 XSLT



您可以使用 XDocument.CreateNavigator() 方式,然后使用 XslCompiledTransform.Transform() 方式来进行改造。



XSLT转换本身很简单

 <的xsl:样式版本=1.0
的xmlns:XSL = http://www.w3.org/1999/XSL/Transform\">
< XSL:输出中省略的XML声明=YES缩进=YES/>

<的xsl:模板匹配=节点()| @ *>
< XSL:复制>
< XSL:申请模板选择=节点()| @ */>
< / XSL:复制>
< / XSL:模板>

<的xsl:模板匹配=
场[@名称='F'] /场[@名称='0']
|
场[ @名称='b'] /场[不是(@名称='3')]
/>
< / XSL:样式>



时,所提供的XML文档应用,它产生了想要的,正确的结果

 <&领域GT; 
<字段名=F>
<字段名=1>
< VALUE> F.1的东西与LT; /值>
< /场>
<字段名=2>
< VALUE> F.2东西< /值>
< /场>
< /场>
<字段名=B>
<字段名=3>
< VALUE> B.3东西< /值>
< /场>
< /场>
< /田>


I'm trying to filter an XML file using XPath. The XPath that I'm using is definitely filtering to the data that I want, but I'm just not sure how to filter the file overall.

Here's the sample XML file:

<fields>
    <field name='F'>
        <field name='0'><value>F.0 stuff</value></field>
        <field name='1'><value>F.1 stuff</value></field>
        <field name='2'><value>F.2 stuff</value></field>
    </field>
    <field name='B'>
        <field name='0'><value>B.0 stuff</value></field>
        <field name='1'><value>B.1 stuff</value></field>
        <field name='2'><value>B.2 stuff</value></field>
        <field name='3'><value>B.3 stuff</value></field>
    </field>
</fields>

Here's the desired output:

<fields>
    <field name='F'>
        <field name='1'><value>F.1 stuff</value></field>
        <field name='2'><value>F.2 stuff</value></field>
    </field>
    <field name='B'>
        <field name='3'><value>B.3 stuff</value></field>
    </field>
</fields>

The solution does not necessarily have to be solved by XPath, but since this is a .NET application, .NET APIs would be appreciated! The following code can be cut and pasted into LINQPad with no edits to see what I'm trying to do.

var doc = XDocument.Parse(@"
<fields>
    <field name='F'>
        <field name='0'><value>F.0 stuff</value></field>
        <field name='1'><value>F.1 stuff</value></field>
        <field name='2'><value>F.2 stuff</value></field>
    </field>
    <field name='B'>
        <field name='0'><value>B.0 stuff</value></field>
        <field name='1'><value>B.1 stuff</value></field>
        <field name='2'><value>B.2 stuff</value></field>
        <field name='3'><value>B.3 stuff</value></field>
    </field>
</fields>");
doc.Dump("Original XML");

var xpath = "//fields/field[@name='F']/field[@name='1' or @name='2'] | //fields/field[@name='B']/field[@name='3']";
doc.XPathSelectElements(xpath).Dump("XPath Combined");

var desired = XDocument.Parse(@"
<fields>
    <field name='F'>
        <field name='1'><value>F.1 stuff</value></field>
        <field name='2'><value>F.2 stuff</value></field>
    </field>
    <field name='B'>
        <field name='3'><value>B.3 stuff</value></field>
    </field>
</fields>");
desired.Dump("Desired Filtered XML");

EDIT: I completely missed XML Transforms - thank you for the solution! Here's the solution you can paste into LINQPad to see it working:

var filterString = @"@name=""F""]/field[@name=""0""]  | field[@name=""B""]/field[not(@name=""3"")";
var xslFmt = @"
<xsl:stylesheet version='1.0'
 xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
 <xsl:output omit-xml-declaration='yes' indent='yes'/>

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

 <xsl:template match=
  'field[{0}]
  '/>
</xsl:stylesheet>";
var xslMarkup = string.Format(xslFmt, filterString);

var xmlTree = XDocument.Parse(@"
<fields>
    <field name='F'>
        <field name='0'><value>F.0 stuff</value></field>
        <field name='1'><value>F.1 stuff</value></field>
        <field name='2'><value>F.2 stuff</value></field>
    </field>
    <field name='B'>
        <field name='0'><value>B.0 stuff</value></field>
        <field name='1'><value>B.1 stuff</value></field>
        <field name='2'><value>B.2 stuff</value></field>
        <field name='3'><value>B.3 stuff</value></field>
    </field>
</fields>");
xmlTree.Dump("Original XML");

// Code from MSDN: http://msdn.microsoft.com/en-us/library/bb675186.aspx
var newTree = new XDocument();
using (var writer = newTree.CreateWriter()) {
    // Load the style sheet.
    var xslt = new XslCompiledTransform();
    xslt.Load(XmlReader.Create(new StringReader(xslMarkup)));

    // Execute the transform and output the results to a writer.
    xslt.Transform(xmlTree.CreateReader(), writer);
}

newTree.Dump("Transformed XML");

解决方案

XPath is a query language and it cannot be used to produce a modified XML document.

The technology which was especially designed for such transformations is called XSLT.

You can use the XDocument.CreateNavigator() method and then use one of the overloads of the XslCompiledTransform.Transform() method to carry out the transformation.

The XSLT transformation itself is very simple:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

 <xsl:template match=
  "field[@name='F']/field[@name='0']
  |
   field[@name='B']/field[not(@name='3')]
  "/>
</xsl:stylesheet>

when applied on the provided XML document, it produces the wanted, correct result:

<fields>
    <field name="F">
        <field name="1">
            <value>F.1 stuff</value>
        </field>
        <field name="2">
            <value>F.2 stuff</value>
        </field>
    </field>
    <field name="B">
        <field name="3">
            <value>B.3 stuff</value>
        </field>
    </field>
</fields>

这篇关于尝试使用XPath来过滤XML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆