将XPath属性值中的科学计数法解析为数字。

huangapple go评论59阅读模式
英文:

XmlDocument Parse scientific notation in xpath attribute value to a number

问题

我有一个XML文件,其中的值以科学计数法保存,我需要对这个值进行一些比较。但是科学计数法的数字不按预期工作。

下面是我的代码:

XmlDocument doc = new XmlDocument();
doc.LoadXml("<MainLevel><SubLevel Name=\"test\"  Amount=\"0.0E0\"></SubLevel></MainLevel>");

XmlNodeList? xmlLevelsList1 = doc.SelectNodes("MainLevel/SubLevel[@Amount<=275.00]"); // 这不返回任何内容,因为0.0E0是科学计数法
doc.LoadXml("<MainLevel><SubLevel Name=\"test\"  Amount=\"0.00\"></SubLevel></MainLevel>");

XmlNodeList? xmlLevelsList2 = doc.SelectNodes("MainLevel/SubLevel[@Amount<=275.00]"); // 这不返回任何内容,因为0.00是正确的格式

我希望xmlLevelsList1 返回1个节点,而不是0。它返回0是因为

"0.0E0" 不是有效的数字。

英文:

I have XML where the values are saved in scientific notation and I need to preform some comparisons on that value . But the scientific notation numbers are not working as expected.

Below is the code I have:

XmlDocument doc = new XmlDocument();
doc.LoadXml(&quot;&lt;MainLevel&gt;&lt;SubLevel Name=\&quot;test\&quot;  Amount=\&quot;0.0E0\&quot;&gt;&lt;/SubLevel&gt;&lt;/MainLevel&gt;&quot;);
    
XmlNodeList? xmlLevelsList1 = doc.SelectNodes(&quot;MainLevel/SubLevel[@Amount&lt;=275.00]&quot;);// this does not return anything because 0.0E0 is in scientific notation                
doc.LoadXml(&quot;&lt;MainLevel&gt;&lt;SubLevel Name=\&quot;test\&quot;  Amount=\&quot;0.00\&quot;&gt;&lt;/SubLevel&gt;&lt;/MainLevel&gt;&quot;);

XmlNodeList? xmlLevelsList2 = doc.SelectNodes(&quot;MainLevel/SubLevel[@Amount&lt;=275.00]&quot;); this does not return anything because 0.00 is a good format

I want xmlLevelsList1 to return 1 node instead of 0. It is returning 0 because

> "0.0E0" is not a valid number.

答案1

得分: 1

以下是翻译好的内容:

最好使用 *LINQ to XML* API。它自2007年以来就可在.Net Framework中使用。

正如 @zx485 已经指出的:*&quot;XSLT 1.0不支持科学计数法。&quot;*

因此,我们无法使用XPath表达式。

在.Net方面将其转换为 **double** 数据类型即可完成任务。

**c#**

void Main()
{
    XDocument doc = XDocument.Parse(@&quot;&lt;MainLevel&gt;
        &lt;SubLevel Name=&#39;test&#39; Amount=&#39;0.0E0&#39;&gt;&lt;/SubLevel&gt;
        &lt;SubLevel Name=&#39;test1&#39;  Amount=&#39;10.0E1&#39;&gt;&lt;/SubLevel&gt;
        &lt;SubLevel Name=&#39;test1&#39;  Amount=&#39;4.0E5&#39;&gt;&lt;/SubLevel&gt;
        &lt;SubLevel Name=&#39;test1&#39;  Amount=&#39;2.75E2&#39;&gt;&lt;/SubLevel&gt;
        &lt;SubLevel Name=&#39;test1&#39;  Amount=&#39;2.76E2&#39;&gt;&lt;/SubLevel&gt;
    &lt;/MainLevel&gt;&quot;);
    
    var xmlLevelsList1 = doc.Descendants(&quot;SubLevel&quot;)
        .Where(d =&gt; double.Parse(d.Attribute(&quot;Amount&quot;).Value) &lt;= 275.00);
    Console.WriteLine(xmlLevelsList1);
}

**Output**

&lt;SubLevel Name=&quot;test&quot; Amount=&quot;0.0E0&quot;&gt;&lt;/SubLevel&gt;
&lt;SubLevel Name=&quot;test1&quot; Amount=&quot;10.0E1&quot;&gt;&lt;/SubLevel&gt;
&lt;SubLevel Name=&quot;test1&quot; Amount=&quot;2.75E2&quot;&gt;&lt;/SubLevel&gt;
英文:

It is better to use LINQ to XML API. It is available in the .Net Framework since 2007.

As @zx485 already pointed out: "XSLT 1.0 does not have support for scientific notation."

So, we cannot use an XPath expression.

Converting to a double data type on the .Net side does the job.

c#

void Main()
{
	XDocument doc = XDocument.Parse(@&quot;&lt;MainLevel&gt;
			&lt;SubLevel Name=&#39;test&#39; Amount=&#39;0.0E0&#39;&gt;&lt;/SubLevel&gt;
			&lt;SubLevel Name=&#39;test1&#39;  Amount=&#39;10.0E1&#39;&gt;&lt;/SubLevel&gt;
		    &lt;SubLevel Name=&#39;test1&#39;  Amount=&#39;4.0E5&#39;&gt;&lt;/SubLevel&gt;
		    &lt;SubLevel Name=&#39;test1&#39;  Amount=&#39;2.75E2&#39;&gt;&lt;/SubLevel&gt;
		    &lt;SubLevel Name=&#39;test1&#39;  Amount=&#39;2.76E2&#39;&gt;&lt;/SubLevel&gt;
		&lt;/MainLevel&gt;&quot;);
	
	var xmlLevelsList1 = doc.Descendants(&quot;SubLevel&quot;)
		.Where(d =&gt; double.Parse(d.Attribute(&quot;Amount&quot;).Value) &lt;= 275.00);
	Console.WriteLine(xmlLevelsList1);
}

Output

&lt;SubLevel Name=&quot;test&quot; Amount=&quot;0.0E0&quot;&gt;&lt;/SubLevel&gt;
&lt;SubLevel Name=&quot;test1&quot; Amount=&quot;10.0E1&quot;&gt;&lt;/SubLevel&gt;
&lt;SubLevel Name=&quot;test1&quot; Amount=&quot;2.75E2&quot;&gt;&lt;/SubLevel&gt;

答案2

得分: 0

The number() function can be used in XPath 1.0

/MainLevel/SubLevel[number(@Amount) &lt;= 275.00]

Given

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;MainLevel&gt;
    &lt;SubLevel Name=&quot;test&quot;  Amount=&quot;0.0E0&quot;&gt;&lt;/SubLevel&gt;
    &lt;SubLevel Name=&quot;test1&quot;  Amount=&quot;10.0E1&quot;&gt;&lt;/SubLevel&gt;
    &lt;SubLevel Name=&quot;test1&quot;  Amount=&quot;4.0E5&quot;&gt;&lt;/SubLevel&gt;
    &lt;SubLevel Name=&quot;test1&quot;  Amount=&quot;2.75E2&quot;&gt;&lt;/SubLevel&gt;
    &lt;SubLevel Name=&quot;test1&quot;  Amount=&quot;2.76E2&quot;&gt;&lt;/SubLevel&gt;
&lt;/MainLevel&gt;

Will return

&lt;SubLevel Name=&quot;test&quot; Amount=&quot;0.0E0&quot;/&gt;
&lt;SubLevel Name=&quot;test1&quot; Amount=&quot;10.0E1&quot;/&gt;
&lt;SubLevel Name=&quot;test1&quot; Amount=&quot;2.75E2&quot;/&gt;

Tested with xmllint that uses libxml2

 xmllint --xpath &#39;/MainLevel/SubLevel[number(@Amount) &lt;= 275.00]&#39; tmp.xml
&lt;SubLevel Name=&quot;test&quot; Amount=&quot;0.0E0&quot;/&gt;
&lt;SubLevel Name=&quot;test1&quot; Amount=&quot;10.0E1&quot;/&gt;
&lt;SubLevel Name=&quot;test1&quot; Amount=&quot;2.75E2&quot;/&gt;

Testing with python lxml

from lxml import etree
tree = etree.parse(&quot;tmp.xml&quot;)
[e.get(&#39;Amount&#39;) for e in tree.xpath(&#39;/MainLevel/SubLevel[number(@Amount) &lt;= 275.00]&#39;)]
[&#39;0.0E0&#39;, &#39;10.0E1&#39;, &#39;2.75E2&#39;]
英文:

The number() function can be used in XPath 1.0

/MainLevel/SubLevel[number(@Amount) &lt;= 275.00]

Given

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;MainLevel&gt;
    &lt;SubLevel Name=&quot;test&quot;  Amount=&quot;0.0E0&quot;&gt;&lt;/SubLevel&gt;
    &lt;SubLevel Name=&quot;test1&quot;  Amount=&quot;10.0E1&quot;&gt;&lt;/SubLevel&gt;
    &lt;SubLevel Name=&quot;test1&quot;  Amount=&quot;4.0E5&quot;&gt;&lt;/SubLevel&gt;
    &lt;SubLevel Name=&quot;test1&quot;  Amount=&quot;2.75E2&quot;&gt;&lt;/SubLevel&gt;
    &lt;SubLevel Name=&quot;test1&quot;  Amount=&quot;2.76E2&quot;&gt;&lt;/SubLevel&gt;
&lt;/MainLevel&gt;

Will return

&lt;SubLevel Name=&quot;test&quot; Amount=&quot;0.0E0&quot;/&gt;
&lt;SubLevel Name=&quot;test1&quot; Amount=&quot;10.0E1&quot;/&gt;
&lt;SubLevel Name=&quot;test1&quot; Amount=&quot;2.75E2&quot;/&gt;

Tested with xmllint that uses libxml2

 xmllint --xpath &#39;/MainLevel/SubLevel[number(@Amount) &lt;= 275.00]&#39; tmp.xml
&lt;SubLevel Name=&quot;test&quot; Amount=&quot;0.0E0&quot;/&gt;
&lt;SubLevel Name=&quot;test1&quot; Amount=&quot;10.0E1&quot;/&gt;
&lt;SubLevel Name=&quot;test1&quot; Amount=&quot;2.75E2&quot;/&gt;

Testing with python lxml

from lxml import etree
tree = etree.parse(&quot;tmp.xml&quot;)
[e.get(&#39;Amount&#39;) for e in tree.xpath(&#39;/MainLevel/SubLevel[number(@Amount) &lt;= 275.00]&#39;)]
[&#39;0.0E0&#39;, &#39;10.0E1&#39;, &#39;2.75E2&#39;]

答案3

得分: 0

使用Saxon.NET:

using System.Xml;
using Saxon.Api;

XmlDocument doc = new XmlDocument();
doc.LoadXml("&lt;MainLevel&gt;&lt;SubLevel Name=\&quot;test\&quot;  Amount=\&quot;0.0E0\&quot;&gt;&lt;/SubLevel&gt;&lt;/MainLevel&gt;");

XmlNodeList? xmlLevelsList1 = doc.SelectNodes("MainLevel/SubLevel[@Amount&lt;=275.00]");// 因为0.0E0采用科学计数法,所以这里没有返回任何内容

Console.WriteLine(xmlLevelsList1.Count);

Processor processor = new Processor();

var docBuilder = processor.NewDocumentBuilder();

var xdmDoc = docBuilder.Wrap(doc);

var xpathCompiler = processor.NewXPathCompiler();

var xdmResult = xpathCompiler.Evaluate("MainLevel/SubLevel[@Amount&lt;=275.00]", xdmDoc);

Console.WriteLine(xdmResult.Count);

Output:

0
1

请注意,虽然您可以对Microsoft DOM(即XmlDocument/XmlNode)运行XPath 3.1,但Saxon有自己的树模型,建议只在无法切换到Saxon的本机树模型的遗留代码中使用Microsoft DOM
英文:

Using Saxon.NET:

using System.Xml;
using Saxon.Api;

XmlDocument doc = new XmlDocument();
doc.LoadXml(&quot;&lt;MainLevel&gt;&lt;SubLevel Name=\&quot;test\&quot;  Amount=\&quot;0.0E0\&quot;&gt;&lt;/SubLevel&gt;&lt;/MainLevel&gt;&quot;);
    
XmlNodeList? xmlLevelsList1 = doc.SelectNodes(&quot;MainLevel/SubLevel[@Amount&lt;=275.00]&quot;);// this does not return anything because 0.0E0 is in scientific notation                

Console.WriteLine(xmlLevelsList1.Count);

Processor processor = new Processor();

var docBuilder = processor.NewDocumentBuilder();

var xdmDoc = docBuilder.Wrap(doc);

var xpathCompiler = processor.NewXPathCompiler();

var xdmResult = xpathCompiler.Evaluate(&quot;MainLevel/SubLevel[@Amount&lt;=275.00]&quot;, xdmDoc);

Console.WriteLine(xdmResult.Count);

Output:

0
1

Do note that, while you can run XPath 3.1 against the Microsoft DOM (i.e. XmlDocument/XmlNode) that Saxon has its own tree model and it is recommended to only use the Microsoft DOM if you have legacy code where you can't switch to Saxon's native tree model.

huangapple
  • 本文由 发表于 2023年6月29日 06:36:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76577104.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定