0

商业应用程序使用 XML 来保存它使用的变量列表。我无法控制 XML 的格式。我可以使用任何版本的.Net.

尝试编写更简单的代码来将UserVar节点分配给我创建的对象。现在我找到包含所有个体的 UserVars 部分的节点UserVars,遍历每个UserVar寻找元素“名称”,然后查看它是否与我想要的变量名称匹配。

例如,我想要变量“已更改”,我将获得一个AcmeVar具有属性的对象(我的创建)NameWidth设置为“已更改”和 1。但我必须手动迭代代码。

似乎我正在努力做到这一点。理想情况下,我喜欢使用 Linq 返回UserVar具有匹配元素名称的节点。Stackoverflow 上的类似问题没有遵循类似的模式,或者至少不是我所看到的。并非所有变量都使用所有元素类型。

示例:XML

<?xml version="1.0" encoding="UTF-8"?>
<Application>
  <Vars>
    <UserVars>
      <UserVar>
        <Name>"Quantity"</Name>
        <Width>4</Width>
        <VarValue>"1"</VarValue>
      </UserVar>
      <UserVar>
        <Name>"Printers"</Name>
        <Width>255</Width>
      </UserVar>
      <UserVar>
        <Name>"Changed"</Name>
        <Width>1</Width>
      </UserVar>
      <UserVar>
        <Name>"Weight"</Name>
        <VarValue>"450.1"</VarValue>
      </UserVar>
    </UserVars>
  </Vars>
</Application>

当前代码:

public static bool GetVariable(string xmlDocNm, string varName, out AcmeVariable acmeVar)
{
  // Returns true if found without error

  bool result = false;
  acmeVar = new AcmeVariable ();

  try {
    XPathDocument doc = new XPathDocument(xmlDocNm);
    XPathNavigator nav = doc.CreateNavigator();

    // Compile a standard XPath expression
    XPathExpression expr;
    expr = nav.Compile(AcmeConst.XPathInternalVariable);
    XPathNodeIterator iterator = nav.Select(expr);

    // Iterate on the node set
    try {
      bool variableFound;
      bool skipNode;

      char[] CharsToTrim = { '\"' }; // 
      while (iterator.MoveNext()) {
        variableFound = false;
        skipNode = false;
        XPathNavigator nav2 = iterator.Current.Clone();
        if (nav2.MoveToFirstChild()) {
          // nav2 points to the first element in an UserVar Node
          acmeVar = new AcmeVariable ();               //Start with a fresh Acme Variable

          if (nav2.LocalName == AcmeConst.AttrName) {
            variableFound = true;
            skipNode = nav2.Value.Trim(CharsToTrim) != varName;
          }
          if (!skipNode) {
            AssignXMLNavNodetoAcmeVar(nav2, acmeVar);
            while (nav2.MoveToNext() && !skipNode) {
              if (nav2.LocalName == AcmeConst.AttrName) {
                variableFound = true;
                skipNode = nav2.Value.Trim(CharsToTrim) != varName;
              }
              AssignXMLNavNodetoAcmeVar(nav2, acmeVar);
            }
          }
        }
        if (variableFound && !skipNode) {
          result = true;
          break; //We have found the variable and collected all elements
        }
        else {
          acmeVar = null;
        }
      }
    }
    catch (Exception ex) {
      MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
      acmeVar = null;
      result = false;
    }
  }
  catch (Exception ex) {
    MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
    acmeVar = null;
    result = false;
  }

  return result;
} 
4

2 回答 2

3

尝试这个:

var queryValue = "Quantity";
var xDoc = XDocument.Load(@"UserVars.xml");//This is your xml path value

var userVar = xDoc.Descendents("UserVar").Where(x => x.Element("Name").Value == queryValue )
                  .FirstOrDefault();

var name     = userVar.Element("Name").Value ?? string.Empty;
var width    = userVar.Element("Width").Value ?? string.Empty;
var varValue = userVar.Element("VarValue").Value ?? string.Empty;

我只是想对您的 XML 进行评论,尤其是在<Name>"Quantity"</Name>元素值包含在其中的部分""

但是如果你对 xml 没有约束,你只需要转义那些". 例如。var queryValue = @""Quantity"";

于 2013-04-28T23:51:32.723 回答
1

假设您的密钥是名称,并且所有节点都将包含它,那么这应该可以工作:

string valImLookingFor = "\"Changed\"";
XDocument doc = XDocument.Load("file"); // or XDocument doc = XDocument.Parse(xmlString);

var node = doc.Descendants("UserVar").Where(x => x.Element("Name").Value == valImLookingFor).First();

这应该让你得到你的节点,然后你可以拉出你需要的子节点值。

于 2013-04-28T23:41:55.133 回答