ASP.NET Razor Pages:创建 HTML 表示 Xml 的结构

ASP.NET Razor Pages: Create HTML Representing Structure of Xml

我正在尝试在 xml(~/server_settings.xml):

中显示数据
<?xml version="1.0" encoding="utf-8"?>
<site>
    <general>
        <name>Venture Corp</name>
        <url>http://anerdsplayground.com/</url>
        <developer>Otard95</developer>
    </general>
    <ore_contracts>
        <use_system description="This is the system id the ore contract app gets its prices from">30000142</use_system>
    </ore_contracts>
</site>

在我的网站上。但我想用 css 给它一些样式,并为每个具有文本值的节点添加一个带有输入的表单,以便我以后可以编辑内容。

我也希望能够读取任何新节点,因为该文件将来会扩展。所以本质上它需要读取动态 xml.

我目前正在使用此代码:

@using System.Xml
@using System.Xml.Linq
@using System.Xml.XPath

@functions{

    XmlDocument doc = null;
    string output = "";

    XmlDocument set_doc{
        set{
            doc = value;
        }
    }

    string write_xml(string path){

        // Add start tag and any attributes that this node may have
        output += "<div ";

        if(doc.SelectSingleNode(path).Attributes.Count > 0){
            // As the description attribute is to be added to a p tag save it for later
            string desc = "";

            // loop through all attributes
            foreach(XmlAttribute att in doc.SelectSingleNode(path).Attributes){
                if(att.Name == "description"){ // If description attribute exists save it for later
                    desc = att.InnerText;
                }else{ // Write attribute to output
                    output += att.Name + '=' + '"' + att.InnerText + '"' + ' ';
                }
            }
            // Close starting tag
            output += ">";

            // If node has description attribute add to <p> tag
            if(desc != ""){
                output += "<p>" + desc + "</p><br/>";
            }
        }

        // If current node has one or more child nodes execute this function for each of them
        if(doc.SelectSingleNode(path).HasChildNodes){
            foreach(XmlNode next_node in doc.SelectSingleNode(path).ChildNodes){
                string new_path = path + "/" + next_node.Name; // Create path for next element
                write_xml(new_path); // write next inner node
            }

            // Close this node
            output += "</div>";
        }else{ // No inner nodes add content of current node and close element
            output += "<input type=" + '"' + "text" + '"' + " name=" + '"' + "node_content" + '"' + " value=" + '"' + doc.SelectSingleNode(path).InnerText + '"' + " />";
        }
        return output;
    }
}

@{
    // Get xml from eve-centeral with current ore-prices and creat dictionary
    XmlDocument doc = new XmlDocument();
    doc.Load(Server.MapPath("~/server_settings.xml"));
    string root = "/site";

    set_doc = doc;
}

<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title></title>
        <style>

        </style>
    </head>
    <body>
        @Html.Raw(write_xml(root));
    </body>
</html>

但是我得到这个错误:

Server Error in '/' Application.

Expression must evaluate to a node-set.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.Xml.XPath.XPathException: Expression must evaluate to a node-set.

Source Error: 


Line 19:         output += "<div ";
Line 20: 
Line 21: error-->if(doc.SelectSingleNode(path).Attributes.Count > 0){
Line 22:             // As the description attribute is to be added to a p tag save it for later
Line 23:             string desc = "";

Line: 21 

Stack Trace: 


[XPathException: Expression must evaluate to a node-set.]
   MS.Internal.Xml.XPath.XPathParser.ParseNodeTest(AstNode qyInput, AxisType axisType, XPathNodeType nodeType) +5596737
   MS.Internal.Xml.XPath.XPathParser.ParseStep(AstNode qyInput) +75
   MS.Internal.Xml.XPath.XPathParser.ParseRelativeLocationPath(AstNode qyInput) +18
   MS.Internal.Xml.XPath.XPathParser.ParseLocationPath(AstNode qyInput) +118
   MS.Internal.Xml.XPath.XPathParser.ParsePathExpr(AstNode qyInput) +30
   MS.Internal.Xml.XPath.XPathParser.ParseUnionExpr(AstNode qyInput) +19
   MS.Internal.Xml.XPath.XPathParser.ParseUnaryExpr(AstNode qyInput) +44
   MS.Internal.Xml.XPath.XPathParser.ParseMultiplicativeExpr(AstNode qyInput) +21
   MS.Internal.Xml.XPath.XPathParser.ParseAdditiveExpr(AstNode qyInput) +21
   MS.Internal.Xml.XPath.XPathParser.ParseRelationalExpr(AstNode qyInput) +21
   MS.Internal.Xml.XPath.XPathParser.ParseEqualityExpr(AstNode qyInput) +21
   MS.Internal.Xml.XPath.XPathParser.ParseAndExpr(AstNode qyInput) +19
   MS.Internal.Xml.XPath.XPathParser.ParseOrExpr(AstNode qyInput) +19
   MS.Internal.Xml.XPath.XPathParser.ParseExpresion(AstNode qyInput) +30
   MS.Internal.Xml.XPath.XPathParser.ParseXPathExpresion(String xpathExpresion) +54
   System.Xml.XPath.XPathExpression.Compile(String xpath, IXmlNamespaceResolver nsResolver) +51
   System.Xml.XPath.XPathNavigator.Select(String xpath) +14
   System.Xml.XmlNode.SelectNodes(String xpath) +45
   System.Xml.XmlNode.SelectSingleNode(String xpath) +7
   ASP._Page_Administrative_Edit_Settings_cshtml.write_xml(String path) in c:\Users\Otard95\Google Drive\Personal\WebSites\VentureCorpDrive\Administrative\Edit_Settings.cshtml:21
   ASP._Page_Administrative_Edit_Settings_cshtml.write_xml(String path) in c:\Users\Otard95\Google Drive\Personal\WebSites\VentureCorpDrive\Administrative\Edit_Settings.cshtml:46
   ASP._Page_Administrative_Edit_Settings_cshtml.write_xml(String path) in c:\Users\Otard95\Google Drive\Personal\WebSites\VentureCorpDrive\Administrative\Edit_Settings.cshtml:46
   ASP._Page_Administrative_Edit_Settings_cshtml.write_xml(String path) in c:\Users\Otard95\Google Drive\Personal\WebSites\VentureCorpDrive\Administrative\Edit_Settings.cshtml:46
   ASP._Page_Administrative_Edit_Settings_cshtml.Execute() in c:\Users\Otard95\Google Drive\Personal\WebSites\VentureCorpDrive\Administrative\Edit_Settings.cshtml:78
   System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +197
   System.Web.WebPages.WebPage.ExecutePageHierarchy(IEnumerable`1 executors) +68
   System.Web.WebPages.WebPage.ExecutePageHierarchy() +151
   System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +76
   System.Web.WebPages.WebPageHttpHandler.ProcessRequestInternal(HttpContextBase httpContext) +114

期望的输出(示例):

<html lang="en">
    <body>
        <div>NodeName:
            <div any attributes xml node might have>
                <p>value of attribute named "description"</p>
                <form method="post">
                    <input type="text" name="node_content" value="current content of xml node"/>
                </form>
            </div>
        </div>

        <div any attributes xml node might have>
            <p>value of attribute named "description"</p>
            <form method="post">
                <input type="text" name="node_content" value="current content of xml node"/>
            </form>
        </div>

        ...

    </body>
</html>

我对 System.xml 命名空间还很陌生,所以这可能不是最好的方法。但由于我没有找到好的教程,我唯一的选择是使用试错法。因此,如果您决定回复,请稍微解释一下。如果您手边有好的教程,也许 link,我将不胜感激。

如果我遗漏了什么而您需要更多信息,请提醒我,我会尽快编辑 post。

提前感谢您提供的任何帮助!

按照@har07的建议,我找到了异常发生时path变量的值,我得到了/site/general/name/#text。我不知道的是 XmlElement 的文本内容被认为是 ChildNode

解决方案:

if(doc.SelectSingleNode(path).HasChildNodes && doc.SelectSingleNode(path).FirstChild.GetType().ToString() != "System.Xml.XmlText"){
    foreach(XmlNode next_node in doc.SelectSingleNode(path).ChildNodes){
        string new_path = path + "/" + next_node.Name; // Create path for next element
        write_xml(new_path); // write next inner node
    }

    // Close this node
    output += "</div>";
}else{

编辑:

已将 && doc.SelectSingleNode(path).FirstChild.GetType().ToString() != "System.Xml.XmlText" 添加到 if 语句

非常感谢你@har07