.NET 8.0 не нормализует пробелы для элементов xs: token?

Я работаю с C# и .NET 8.0.6.

У меня есть XSD, который объявляет «корневой» элемент с содержимым 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>

Мой код, который делает следующее:

  1. Считывает XSD как System.Xml.Schema.XmlSchema.
  2. Добавляет схему в System.Xml.Schema.SchemaSet, который затем компилируется.
  3. Создает XmlReader (XsdValidatingReader), используя:
    var xmlReaderSettings = new XmlReaderSettings
    {
        CheckCharacters = true,
        DtdProcessing   = DtdProcessing.Prohibit,
        Schemas         = xmlSchemaSet,
        ValidationType  = ValidationType.Schema,
    };
  1. Загружает экземпляр, используя System.Xml.XmlDocument.Load(xmlReader).

Объект документа дает:

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

В частности, XmlDocument.DocumentElement имеет:

  • InnerXml: "   abc   "
  • URI пространства имен: «http://example.org/scratch»
  • SchemaInfo.SchemaType.TypeCode: «Токен»

В чем вопрос? Посмотрите здесь: oreilly.com/library/view/xml-schema/0596002521/re95.html

Yitzhak Khabinsky 03.07.2024 19:19

Я не уверен, что в .NET DOM (т. е. System.Xml.XmlDocument/XmlNode/XmlElement) вы найдете значения, типизированные схемой. Используйте XPathNavigator/XPathDocument Learn.microsoft.com/en-us/dotnet/api/… . См. также Learn.microsoft.com/en-us/dotnet/standard/data/xml/…

Martin Honnen 03.07.2024 19:38
XmlReaderSettings.IgnoreWhitespace было бы хорошим началом, но это значительные пробелы, потому что текст — это не только пробелы.
Charlieface 03.07.2024 22:51

@YitzhakKhabinsky — Смотри второй абзац. Я не понимаю, почему начальные и конечные пробелы не были удалены из содержимого элемента, набранного как xs:token.

voidp 03.07.2024 23:35

@Charlieface — XmlReaderSettings.IgnoreWhitespace контролирует игнорирование незначительных пробелов. Однако пробелы в содержимом элемента имеют большое значение.

voidp 03.07.2024 23:46

@MartinHonnen — я предполагаю, что да, поскольку, как видно в конце вопроса, SchemaInfo.SchemaType.TypeCode: «Токен» соответствует XmlDocument.DocumentElement. Кроме того, я только изучаю XML, поэтому пока не могу экспериментировать с XPath.

voidp 03.07.2024 23:49

Если вы хотите, чтобы кто-то полностью исследовал логику вашего кода, вам следует опубликовать минимально воспроизводимый пример.

mamift 04.07.2024 12:17
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
7
98
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы столкнулись со своеобразными нюансами проверки XSD.

Сначала он применяет тип данных xs:token к значению элемента, сворачивает пробелы и сразу после этого запускает проверку.

Если вам нужно сделать присутствие пробелов недействительным, попробуйте следующий XSD.

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">
        <xs:simpleType>
            <xs:restriction base = "xs:string">
                <xs:pattern value = "[^\s]+"/>
            </xs:restriction>
        </xs:simpleType>
    </xs:element>
</xs:schema>

Кажется, вы подразумеваете, что замена пробелов выполняется для проверки, но результаты не сохраняются в DOM после проверки? Однако .NET (например) дополняет проверенные экземпляры значениями по умолчанию для отсутствующих элементов. Кроме того, в приведенной вами выше ссылке (oreilly) указано, что пространством значений элемента xs:token является строка «после замены пробелов». (См. пример.) Итак, я ожидаю замены пробелов, но подозреваю, что делаю что-то не так.

voidp 04.07.2024 00:33

Вам нужно говорить с точки зрения результатов проверки: действительных или недействительных.

Yitzhak Khabinsky 04.07.2024 01:20

Проверка @voidp не изменяет XML, а просто проверяет, все ли в порядке. В спецификации w3.org/TR/xmlschema11-2/#token говорится, что ограничения на xs:token (например, минимальная/максимальная длина и т. д.) применяются только после свертывания, но это не имеет ничего общего с фактическим изменением XML, это все о проверке. Если XML проверен, соответствующий десериализатор XSD затем проанализирует обрезанное значение. См., например, dotnetfiddle.net/Tt1VDR, где вы можете убедиться, что строка обрезается. Скажем так: сам XML не меняется, меняется то, что вы из него анализируете.

Charlieface 04.07.2024 06:26

@Charlieface Согласен. Меня сбило с толку увеличение информационного набора. Когда я увидел, что добавляются значения по умолчанию, я ошибочно ожидал, что содержимое будет преобразовано в соответствии с типом схемы.

voidp 05.07.2024 18:35
Ответ принят как подходящий

Заполнение не удаляется, поскольку проверка XML-схемы не изменяет содержимое экземплярного документа.

Я ошибочно предположил, что любая нормализация пробелов, примененная к xs:token, сохраняется. Однако в спецификации XSD такие модификации не предусмотрены. Любая нормализация является внутренней для процесса проверки.

Хотя содержимое экземпляра не изменяется во время проверки, его можно дополнить. Добавление значений по умолчанию — один из примеров. Добавление информации в информационный набор после проверки схемы (PSVI) — еще один вариант.

В .NET и C# к информации PSVI узла XML можно получить доступ через XmlNode.SchemaInfo и использовать ее для выполнения преобразования после проверки. Например, если SchemaInfo.SchemaType.TypeCode из XmlTypeCode.Token, приложение может нормализовать пробелы в контенте.

Я все еще думаю, что Learn.microsoft.com/en-us/dotnet/api/… должен дать вам abc, а не `abc` , но кажется, что он действительно просто возвращает ненормализованную строку. Я скорее считаю ошибкой в ​​этом API то, что значение xs:token не возвращается нормализованным.

Martin Honnen 06.07.2024 12:12

@MartinHonnen Рассмотрите возможность публикации этого на github.com/dotnet/runtime/discussions.

voidp 06.07.2024 16:07

Я попытал счастья, чтобы поднять это как потенциальную проблему github.com/dotnet/runtime/issues/104507

Martin Honnen 06.07.2024 16:11

Используя SaxonCS (требуется коммерческая лицензия), вы можете использовать построитель документов с поддержкой схемы для анализа входных XML-данных в документ XDM, а затем получить типизированное значение:

using Saxon.Api;

using Path = System.IO.Path;

using static Saxon.Api.Steps;

var processor = new Processor();

processor.SchemaManager.Compile(new Uri(Path.Combine(Environment.CurrentDirectory, "schema1.xsd")));

var schemaValidator = processor.SchemaManager.NewSchemaValidator();

var docBuilder = processor.NewDocumentBuilder();

docBuilder.SchemaValidator = schemaValidator;

var xdmNode = docBuilder.Build(new Uri(Path.Combine(Environment.CurrentDirectory, "sample1.xml")));

foreach (var item in xdmNode.OutermostElement.Select(Child("item")))
{
    foreach (var child in item.Children())
    {
        Console.WriteLine($"Child {child.NodeName}: typed value: |{child.TypedValue}|");
    }
}

Пример XML:

<?xml version = "1.0" encoding = "utf-8" ?>
<root>
  <item>
    <string>   abc   </string>
    <token>   abc   </token>
    <date>   2024-07-01   </date>
    <tokens>   foo   bar   baz </tokens>
  </item>
  <item>
    <string>   abc   </string>
    <token>   abc   </token>
    <date>   2024-07-01   </date>
    <tokens>   foo   bar   baz </tokens>
  </item>
</root> 

Пример схемы:

<xs:schema xmlns:xs = "http://www.w3.org/2001/XMLSchema">
  <xs:element name = "root">
    <xs:complexType>
      <xs:sequence maxOccurs = "unbounded">
        <xs:element name = "item">
          <xs:complexType>
            <xs:sequence>
              <xs:element name = "string" type = "xs:string"/>
              <xs:element name = "token" type = "xs:token"/>
              <xs:element name = "date" type = "xs:date"/>
              <xs:element name = "tokens" type = "xs:NMTOKENS"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Пример вывода программы:

Child string: typed value: |   abc   |
Child token: typed value: |abc|
Child date: typed value: |2024-07-01|
Child tokens: typed value: |"foo"
"bar"
"baz"|
Child string: typed value: |   abc   |
Child token: typed value: |abc|
Child date: typed value: |2024-07-01|
Child tokens: typed value: |"foo"
"bar"
"baz"|

Другие вопросы по теме