You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8.0中xs:token元素未自动规范化空白字符?

.NET 8中xs:token类型元素验证后未自动去除前后空白的问题

我使用C#和.NET 8.0.6开发,定义了一个XSD,其中root元素的类型为xs:token。按照xs:token的定义,它应该自动去除内容前后的空白,但验证包含前后空白的实例文档后,这些空白却被保留了下来,不符合预期。

XSD内容

<?xml version='1.0'?>

<xs:schema
    targetNamespace = "http://example.org/scratch"
    xmlns           = "http://example.org/scratch"
    xmlns:xs        = "http://www.w3.org/2001/XMLSchema">

<xs:element name="root" type="xs:token"/>

</xs:schema>

实例文档内容

<?xml version='1.0'?>

<pre:root xmlns:pre="http://example.org/scratch">   abc   </pre:root>

执行步骤

  • 将XSD读取为System.Xml.Schema.XmlSchema对象
  • 将该架构添加到System.Xml.Schema.SchemaSet并编译
  • 创建XmlReader时使用以下配置:
var xmlReaderSettings = new XmlReaderSettings
{
    CheckCharacters = true,
    DtdProcessing   = DtdProcessing.Prohibit,
    Schemas         = xmlSchemaSet,
    ValidationType  = ValidationType.Schema,
};
  • 使用System.Xml.XmlDocument.Load(xmlReader)加载实例文档

加载后的结果

加载后的文档内容如下:

<?xml version="1.0"?>
<pre:root xmlns:pre="http://example.org/scratch">   abc   </pre:root>

XmlDocument.DocumentElement的相关属性:

  • InnerXml: " abc "
  • NamespaceURI: "http://example.org/scratch"
  • SchemaInfo.SchemaType.TypeCode: Token

解决方法

问题在于XmlDocument仅负责验证内容是否符合XSD约束,不会主动根据类型规则修改文档内容,因此不会自动执行xs:token的空白规范化操作。以下是几种实现空白处理的方案:

方案1:通过XmlReader直接获取规范化值

XmlReader在读取符合xs:token类型的元素内容时,会自动处理空白,直接读取即可得到规范化后的值:

using (var reader = XmlReader.Create("实例文档路径", xmlReaderSettings))
{
    while (reader.Read())
    {
        if (reader.NodeType == XmlNodeType.Element && reader.LocalName == "root")
        {
            string normalizedValue = reader.ReadElementContentAsString();
            // normalizedValue 结果为"abc",前后空白已去除
            break;
        }
    }
}

方案2:加载文档后手动规范化

如果需要保留文档结构,可在加载后通过SchemaInfo判断元素类型,手动执行空白处理:

XmlDocument doc = new XmlDocument();
doc.Load(reader);
XmlElement root = doc.DocumentElement;

if (root.SchemaInfo.SchemaType is XmlSchemaSimpleType simpleType && 
    simpleType.TypeCode == XmlTypeCode.Token)
{
    string normalizedValue = XmlConvert.ToString(XmlConvert.ToToken(root.InnerText));
    root.InnerText = normalizedValue;
    // 处理后root的InnerText为"abc"
}

方案3:使用XmlSerializer反序列化

若可以将XML反序列化为实体类,XmlSerializer会自动处理xs:token类型的空白:

[XmlRoot(Namespace = "http://example.org/scratch")]
public class Root
{
    [XmlText]
    public string Value { get; set; }
}

var serializer = new XmlSerializer(typeof(Root));
using (var reader = XmlReader.Create("实例文档路径", xmlReaderSettings))
{
    Root rootObj = (Root)serializer.Deserialize(reader);
    // rootObj.Value 结果为"abc"
}

内容的提问来源于stack exchange,提问作者voidp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 16:30:05