0

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

<?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:

<?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,我可以随时获取 Prioridad 属性之一:

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

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

或: '/ConvenioAladi/Operaciones/Operacion[@Prioridad='Alta'] | /ConvenioAladi/Operaciones/Operacion[@Prioridad='Media'] | /ConvenioAladi/Operaciones/Operacion[@Prioridad='Baja']'

我总是把原始的 XML 拿回来,有没有实现我之前提到的?谢谢

4

2 回答 2

2

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

有几种方法可以实现:

XSLT

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

一旦您学习了 XSLT,做这种事情就变得非常容易。如:

<?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 路线,这意味着您可以升级您的查询,而无需重新编译您的软件。这可能是您希望使用的解决方案。

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

XPath 文档

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

假设docXmlDocument,您可以执行以下操作将其变成XPathDocument

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

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

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(您可能想在此处检查语法):

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。

于 2013-10-14T22:57:09.167 回答
0

如前所述,这里有几个选项。为了具体起见,这里有一个完整的 XSLT (1.0) 解决方案,到目前为止只被暗示过:

<?xml version='1.0' encoding='UTF-8'?>

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

  <xsl:template match="*">
    <xsl:variable name="n" select="name (.)"/>
    <xsl:element name="{$n}">
      <xsl:for-each select="@*">
        <xsl:copy-of select="."/>
      </xsl:for-each>
      <xsl:apply-templates select="*"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="/">
    <xsl:apply-templates select="ConvenioAladi"/>
  </xsl:template>

  <xsl:template match="Operaciones">
    <xsl:apply-templates select="Operacion[@Prioridad = &quot;Alta&quot;]"/>
    <xsl:apply-templates select="Operacion[@Prioridad = &quot;Media&quot;]"/>
    <xsl:apply-templates select="Operacion[@Prioridad = &quot;Baja&quot;]"/>
  </xsl:template>
</xsl:stylesheet>

您可以将此样式表应用到您的 XML 中,它会按、、 .Operacion的顺序对节点进行排序。它相当天真地进行:它只是寻找任何具有该属性值的对象,并且(本质上)将其复制到输出中。然后,然后。即使没有节点对其属性具有值(对于其他两个值也是如此),它也会起作用。样式表确实隐含地假设这三个是属性的唯一可能值(如果有这样的节点,它们会被默默地忽略),因此如果您的节点可能具有其他属性值,则样式表需要进行调整。AltaMediaBajaOperacionAltaPrioridadMediaBajaOperacionBajaPrioridadPrioridadOperacionPrioridad

于 2015-04-11T21:15:17.003 回答