【问题标题】:How to prevent XMLReader from unescaping characters如何防止 XMLReader 转义字符
【发布时间】:2012-05-22 14:46:17
【问题描述】:

我想创建一个简单的 XMLreader,它将一个完整的节点(包括子节点)作为文本读取:

string TXML = @"<xml><text>hall&#xF6;le</text></xml>";

XmlReader r = XmlReader.Create(new StringReader(TXML));
r.Read(); r.Read();

string o = r.ReadOuterXml();

ReadOuterXml 完成了这项工作,但它避开了已经转义的标志:

"<text>hallöle</text>"

我希望得到结果:

"<text>hall&#xF6;le</text>"

我怎样才能省略那个“未转义”。我想将这些片段存储到数据库中,并且确实需要转义。此外,我不想解析和重新创建片段。

【问题讨论】:

  • 您能否更改 XML 源以使用 &amp;amp; 转义 &amp; 符号?
  • 当您将数据插入数据库时​​,我认为您希望它是正确的数据,而不是转义的数据。这样您就可以搜索它,并且当您从数据库中读取数据时,它将是正确的。如果您使用 ADO 和参数,则在将数据插入数据库时​​不需要转义数据。
  • 我是中间人。我无法更改来源。此外,如果我将存储的数据返回给客户,他预计它会再次逃脱。这就是为什么我想保持原样。

标签: c# escaping xmlreader


【解决方案1】:

我遇到了类似的问题,我想在从 xml 读取时保留转义字符,但在调用 ReadOuterXml() 时,可能只保留了一些字符并且至少 oane 被转换了(我有 " 而不是 &quot ;)

我的解决方案如下:

string TXML = @"<xml><text>hall&#xF6;le</text></xml>";
TXML = TXML.Replace("&", "&amp;");
XmlTextReader r = new XmlTextReader(new StringReader(TXML));
r.Read(); r.Read();
// now we are at the text element
r.ReadStartElement()
var content = SecurityElement.Escape(r.ReadContentAsString())
r.ReadEndElement()

【讨论】:

    【解决方案2】:

    我找到了两个解决方案。两者都不是很好,但也许你可以告诉我哪个缺点更少。

    这两种解决方案都直接依赖于使用“XmlTextReader”而不是“XmlReader”。它带有属性“LinePosition”,它引导我找到第一个解决方案,并使用方法“ReadChars”作为第二个解决方案的基础。

    方案(1),通过索引从原始字符串中获取数据

    问题:

    • 不适用于流输入
    • 如果 xml 有几行则不起作用

    代码

    string TXML = @"<xml><data></data><rawnode at=""10 4""><text>hall&#xF6;le</text><z d=""2"">3</z></rawnode><data></data></xml>";
    
    //XmlReader r = XmlReader.Create(new StringReader(TXML));
    XmlTextReader r = new XmlTextReader(new StringReader(TXML));
    
    // read to node which shall be retrived "raw"
    while ( r.Read() )
    {
        if ( r.Name.Equals("rawnode") )
            break;
    }
    
    // here we start
    int Begin = r.LinePosition;
    r.Skip();
    int End = r.LinePosition;
    
    // get it out
    string output=TXML.Substring(Begin - 2, End - Begin);
    

    解决方案(2),使用“ReadChars”获取数据

    问题:

    • 我必须解析并重新创建我想要阅读的标签的“外部”标记。
    • 这可能会降低性能。
    • 我可能会引入错误。

    代码:

    // ... again create XmlTextReader and read to rawnode, then:
    // here we start
    int buflen = 15;
    char[] buf = new char[buflen];
    StringBuilder sb= new StringBuilder("<",20);
    
    //get start tag and attributes    
    string tagname=r.Name;
    sb.Append(tagname);
    bool hasAttributes = r.MoveToFirstAttribute();
    while (hasAttributes)
    {
        sb.Append(" " + r.Name + @"=""" + r.Value + @"""");
        hasAttributes = r.MoveToNextAttribute();
    }
    sb.Append(@">");
    r.MoveToContent();
    
    //get raw inner data    
    int cnt;
    while ((cnt = r.ReadChars(buf, 0, buflen)) > 0)
    {
        if ( cnt<buflen )
            buf[cnt]=(char)0;
        sb.Append(buf);
    }
    
    //append end tag    
    sb.Append("</" + tagname + ">");
    
    // get it out
    string output = sb.ToString();
    

    【讨论】:

      【解决方案3】:

      查看您的 xml 标头并验证它是否包含以下内容:&lt;?xml version="1.0" encoding="ISO-8859-9"?&gt;

      对于转义和取消转义,您可以使用 c# 函数 InnerXmlInnerText

      public static string XmlEscape(string unescaped)
      {
          XmlDocument doc = new XmlDocument();
          var node = doc.CreateElement("root");
          node.InnerText = unescaped;
          return node.InnerXml;
      }
      
      public static string XmlUnescape(string escaped)
      {
          XmlDocument doc = new XmlDocument();
          var node = doc.CreateElement("root");
          node.InnerXml = escaped;
          return node.InnerText;
      }
      

      【讨论】:

      • ´string TXML = @"hallöle text>";´ 但是用相同的代码解析那个字符串并没有改变结果。
      • 另外感谢您的方法 Xml(un)Escape,但使用它们意味着读取和重新创建整个内部 XML。这正是我试图省略的。
      【解决方案4】:

      我理解您不想解析和重新创建转义字符的愿望,但我找不到不这样做的方法,除非您完全自定义它。也许这还不错?

      string TXML = @"<xml><text>hall&#xF6;le</text></xml>";
      TXML = TXML.Replace("&", "&amp;");
      XmlTextReader r = new XmlTextReader(new StringReader(TXML));
      r.Read(); r.Read();
      
      string o = r.ReadOuterXml();
      o = o.Replace("&amp;", "&");
      

      【讨论】:

      • 是的,也许这是唯一的方法。感谢那。但是除了有一个非常粗略的解决方案之外,它可能在应用程序性能中是可见的。我从一个大的 XML 中读取了片段,并且不得不多次读取和写入源代码。
      • 同一来源?只需读取一次并将其存储在一个变量中,然后您可以根据需要多次写入。
      猜你喜欢
      • 2011-03-18
      • 2014-09-21
      • 1970-01-01
      • 1970-01-01
      • 2015-09-14
      • 1970-01-01
      • 2011-09-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多