如何使用 XPATH 添加节点 [英] How to appens nodes using XPATH

查看:45
本文介绍了如何使用 XPATH 添加节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,我正在使用 XPATH 和 XML.SelectNodes() 从 XML 文件中提取圆顶数据,我希望这些数据按特定顺序排列,XML 文件是这样的:

Hi everyone I'm using XPATH with XML.SelectNodes() to extract dome data from an XML file, I wish this data to be in certain order, the XML file is like this:

<?xml version='1.0' encoding='UTF-8'?>
    <ConvenioAladi>
       <Operaciones>
         <Operacion Prioridad='Alta' />
         <Operacion Prioridad='Media' />
         <Operacion Prioridad='Alta' />
         <Operacion Prioridad='Baja' />
         <Operacion Prioridad='Baja' />
         <Operacion Prioridad='Media' />
       </Operaciones>
    </ConvenioAladi>

并希望获得这样的 XML:

And wish to obtain an XML like this:

<?xml version='1.0' encoding='UTF-8'?>
    <ConvenioAladi>
       <Operaciones>
         <Operacion Prioridad='Alta' />
         <Operacion Prioridad='Alta' />
         <Operacion Prioridad='Media' />
         <Operacion Prioridad='Media' />
         <Operacion Prioridad='Baja' />
         <Operacion Prioridad='Baja' />
       </Operaciones>
    </ConvenioAladi>

我可以通过提供 XPATH 随时获得一个优先级属性:

I'm capable of obtaining one of the Prioridad attributes at any moment by giving the XPATH:

'/ConvenioAladi/Operaciones/Operacion[@Prioridad='Alta']',

但是如果我尝试这样的事情:'/ConvenioAladi/Operaciones/Operacion[@Prioridad='Alta' 或 @Prioridad='Media' 或 @Prioridad='Baja' ]'

but if I try something like this: '/ConvenioAladi/Operaciones/Operacion[@Prioridad='Alta' or @Prioridad='Media' or @Prioridad='Baja' ]'

或者:'/ConvenioAladi/Operaciones/Operacion[@Prioridad='Alta'] |/ConvenioAladi/Operaciones/Operacion[@Prioridad='媒体'] |/ConvenioAladi/Operaciones/Operacion[@Prioridad='Baja']'

我总是能得到原始的 XML,有没有办法实现我之前提到的?.谢谢

I always get the original XML back, is there anyway of achieving what I mentioned before?. Thanks

推荐答案

您使用的版本中的 XPath 按顺序匹配节点,您无法更改.

XPath in the version you are using matches nodes in order, which you cannot change.

有几种方法可以实现:

一种简单的方法是执行 XSL 转换

One simple way is to perform an XSL Transform

一旦你学会了 XSLT,做这种事情就变得很容易了.如:

Once you learn XSLT, it becomes really easy to do this sort of thing. Such as:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">
    <xsl:template match="Operaciones">
        <xsl:copy>
            <xsl:apply-templates select="Operacion">
                <xsl:sort select="index-of(('Alta','Media','Baja'), @Prioridad)"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

然后您可以轻松查询所有Operaciones.如果您使用 XSLT 路由,这意味着您可以升级您的查询而无需重新编译您的软件.这可能是您希望使用的解决方案.

And then you can query all your Operaciones easily. If you do it the XSLT route, it means that you can upgrade your queries without having to recompile your software. It is probably the solution you wish to utilise.

更新:Mathias 指出我们不是在寻找按字母顺序排序.我将保留下面的解决方案以供参考,但现在我建议选择上面正确的 XSLT 解决方案.

第二种方式更加程序化,它利用了微软自己的特性:

The second way is more programatic, which utilises Microsoft's own features:

假设 doc 是一个 XmlDocument,您可以执行以下操作将其转换为 XPathDocument:

Assuming doc is an XmlDocument, you can do the following to turn it into an XPathDocument:

XPathDocument xpathDoc = new XPathDocument(new XmlNodeReader(doc));

完成后,您可以运行以下查询:

Once you do that, you can run the following query:

XPathNavigator nav = xpathDoc.CreateNavigator();
XPathExpression expression = XPathExpression.Compile(@"//Operacion");
expression.AddSort(@"@Prioridad", XmlSortOrder.Ascending, XmlCaseOrder.None, "", XmlDataType.Text);
XPathNodeIterator iterator = nav.Select(expression);
foreach (XPathNavigator operation in iterator) {
    Console.WriteLine("Found priority '{0}'",operation.GetAttribute("Prioridad",""));
}

林克

第三种方式,使用 Linq(您可能想在此处检查语法):

Linq

Third way, using Linq (you might want to check the syntax here):

XDocument xDoc = XDocument.Load(new XmlNodeReader(doc));
var operations = xDoc.Descendants("Operacion").OrderBy(s=>(string)s.Attribute("Prioridad"));
foreach(var operation in operations) {
    Console.WriteLine("hey -> {0}", operation);
}

我建议你通过 Linq 来做,但如果你正在转换数据,那么每次都使用 XSLT.

I suggest you do it via Linq, but if you are transforming data, then go for XSLT every time.

这篇关于如何使用 XPATH 添加节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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