Список XPath-ов на XElement - PullRequest
1 голос
/ 26 марта 2020

Я пытаюсь получить значение первого совпадения xpath в моем C# -

private string getValue(List<string> xpaths, XElement xml) {
        string stringValue = string.Empty;
        foreach(string xpath in xPaths)
        {
            var value = xml.XPathEvaluate(xpath);

            if (value is IEnumerable)
            {
                foreach (XObject xObject in value)
                {
                    if (xObject is XElement)
                    {
                        stringValue = ((XElement)xObject).Value.FirstOrDefault().ToString();
                        break;
                    }
                    else if (xObject is XAttribute)
                    {
                        stringValue = ((XAttribute)xObject).Value.FirstOrDefault().ToString();
                        break;
                    }
                }
            }
            else
                stringValue = value.ToString();
        }
        return stringValue;

}

Мой список будет выглядеть так -

//Request/Header/Error/text()    
//Request/Header/Error[0]/Details/ErrorMesage/text()
//Request/Header/Error/Details/@code
//Request/Header/Error/Details/StackTrace/text()

В списке XPaths, я хочу go через список и вернуть первое совпадение. XPathEvaluate не работает для меня. Я не уверен, что не так.

Возможные XML значения

<Request>
  <Header>
    <Error>
        <Details>
            <StackTrace>trace</StackTrace>
        </Details>
    <Error>
  </Header>
</Request>


 <Request>
  <Header>
    <Error>
        <Details>
            <ErrorMessage>This is the Error Message1.</ErrorMessage>
        </Details>
    <Error>
    <Error>
        <Details>
            <ErrorMessage>This is the Error Message2.</ErrorMessage>
        </Details>
    <Error>
  </Header>
</Request>

<Request>
  <Header>
    <Error>This is the error message.<Error>
  </Header>
</Request>

<Request>
  <Header>
    <Error>
        <Details code="123">
            <StackTrace>trace</StackTrace>
        </Details>
    <Error>
  </Header>
</Request>

<Request>
  <Header>
    <Error>
        <Details>
            <ErrorMessage>This is the Error Message.</ErrorMessage>
        </Details>
    <Error>
  </Header>
</Request>

Это передается такому методу -

getValue(xpathList, XElement.Parse(xmlString))

Так как я не знаю что xml я получу, я хочу просмотреть список XPath и вернуть первое совпадение. Это может быть либо текст элемента, либо значение атрибута.

1 Ответ

1 голос
/ 27 марта 2020

Во-первых, мы используем XDocument, вы можете использовать XElement, но вам нужно изменить выражение XPath для xpathList, подробнее :
1 - у вас есть ошибка во всех xml тестовых случаях, тег Error не закрыт, затем исправьте их:

<Request>
  <Header>
    <Error>
        <Details>
            <StackTrace>trace</StackTrace>
        </Details>
    </Error>
  </Header>
</Request>

2 - у вас есть ошибка в этом выражении //Request/Header/Error[0]/Details/ErrorMesage/text(), чтобы получить сначала Error используйте 1 не 0, вы также пропустите s в ErrorMesage:

List<string> xPathList = new List<string>
{
    "//Request/Header/Error/text()",
    "//Request/Header/Error[1]/Details/ErrorMessage/text()",
    "//Request/Header/Error/Details/@code",
    "//Request/Header/Error/Details/StackTrace/text()"
};

3 - измените GetValue, как показано в следующем коде:

private string GetValue(List<string> xPaths, XDocument xml)
{
    string stringValue = string.Empty;
    foreach (string xpath in xPaths)
    {
        var value = xml.XPathEvaluate(xpath);

        foreach (XObject xObject in (IEnumerable)value)
        {
            if (xObject is XElement)
            {
                return ((XElement)xObject).Value;
            }
            else if (xObject is XAttribute)
            {
                return ((XAttribute)xObject).Value;
            }
            else
            {
                return ((XText)xObject).Value;
            }
        }
    }

    return stringValue;
}

4 - Тест

string result = GetValue(xPathList, XDocument.Parse(xmlString));

5 - Демо :

 string xml1 = @"<Request>
                <Header>
                    <Error>
                        <Details>
                            <StackTrace>trace</StackTrace>
                        </Details>
                    </Error>
                  </Header>
            </Request>";

string xml2 = @"<Request>
                  <Header>
                    <Error>
                        <Details>
                            <ErrorMessage>This is the Error Message1.</ErrorMessage>
                        </Details>
                    </Error>
                    <Error>
                        <Details>
                            <ErrorMessage>This is the Error Message2.</ErrorMessage>
                        </Details>
                    </Error>
                  </Header>
                </Request>";

string xml3 = @"<Request>
                  <Header>
                    <Error>This is the error message.</Error>
                  </Header>
                </Request>";

string xml4 = @"<Request>
                  <Header>
                    <Error>
                        <Details code=""123"">
                            <StackTrace>trace</StackTrace>
                        </Details>
                    </Error>
                  </Header>
                </Request>";

string xml5 = @"<Request>
          <Header>
            <Error>
                <Details>
                    <ErrorMessage>This is the Error Message.</ErrorMessage>
                </Details>
            </Error>
          </Header>
        </Request>";

List<string> xPathList = new List<string>
{
    "//Request/Header/Error/text()",
    "//Request/Header/Error[1]/Details/ErrorMessage/text()",
    "//Request/Header/Error/Details/@code",
    "//Request/Header/Error/Details/StackTrace/text()"
};

string result1 = GetValue(xPathList, XDocument.Parse(xml1));
Console.WriteLine($"xml1 : {result1}");

string result2 = GetValue(xPathList, XDocument.Parse(xml2));
Console.WriteLine($"xml2 : {result2}");

string result3 = GetValue(xPathList, XDocument.Parse(xml3));
Console.WriteLine($"xml3 : {result3}");

string result4 = GetValue(xPathList, XDocument.Parse(xml4));
Console.WriteLine($"xml4 : {result4}");

string result5 = GetValue(xPathList, XDocument.Parse(xml5));
Console.WriteLine($"xml5 : {result5}");

6 - Результат

xml1 : trace
xml2 : This is the Error Message1.
xml3 : This is the error message.
xml4 : 123
xml5 : This is the Error Message.

Надеюсь, эта помощь

...