c # получить локальный путь .xsd из значения атрибута xsi: schemaLocation

1

Я ищу лучший способ exctract локального пути схемы без использования регулярного выражения.

Образец:

<?xml version="1.0"?>
<ord:order xmlns:ord="http://example.org/ord"
   xmlns:prod="http://example.org/prod"
   xmlns:xs="http://www.w3.org/2001/XMLSchema"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://example.org/prod chapter05prod.xsd
                   http://example.org/ord chapter05ord.xsd">
<items>
    <prod:product>
        <number xsi:type="xs:short">557</number>
        <name>Short-Sleeved Linen Blouse</name>
        <size xsi:nil="true"/>
    </prod:product>
</items>

или

xsi:schemaLocation="http://example.org/prod \\RandomFolder\New\chapter05prod.xsd">

или

 xsi:schemaLocation="chapter05prod.xsd">

Я хотел бы получить локальный путь для файла *.xsd. Есть ли способ сделать это с помощью анализатора xml или xmlResolver или каким-либо другим способом, который не использует регулярное выражение?

Изменение: Я ищу наиболее общий подход, чтобы получить путь для внешних ссылок пути.xsd.

Другой пример:

xsi:noNamespaceSchemaLocation="file://C://Documents and Settings//All Users//Application Data//My Application//MyData.xsd"
Теги:
schema
xml-parsing
xsd

1 ответ

2
Лучший ответ

Вы можете использовать XPath:

using System;
using System.Xml;
using System.Xml.XPath;

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

//@*[local-name()='schemaLocation']

который выберет узел атрибута, который имеет локальное имя schemaLocation (игнорируя его префикс).

Разберите XML файл и получите элемент root (document):

XmlTextReader reader = new XmlTextReader("your-file.xml");
XmlDocument doc = new XmlDocument(); 
doc.Load(reader);
reader.Close();
XmlElement root = doc.DocumentElement;

Затем используйте его для выбора всех атрибутов с именем schemaLocation. Существует только один, поэтому вы можете использовать SelectSingleNode:

XmlNode schemaLocationAttribute = root.SelectSingleNode("//@*[local-name()='schemaLocation']");

Вышеприведенное выражение содержит атрибут. Вы можете получить его содержимое строки, используя schemaLocationAttribute.Value. Оттуда вы можете разделить содержимое, используя пробел, в качестве разделителя:

string[] components = schemaLocationAttribute.Value.Split(null);

И вы получите текст, который вы хотите (chapter05prod.xsd) в components[1]:

Console.WriteLine (components[1]);

(Примечание: вы не можете всегда игнорировать пространства имен XPath - если в вашем файле были другие атрибуты с именем schemaLocation с другим префиксом или без префикса, они также были бы выбраны этим выражением XPath, и это решение не получится.)

  • 0
    Спасибо большое за вашу помощь. Ваше решение кажется полезным в тех же случаях. Я буду голосовать за это, но я буду ждать еще пару дней для более общего подхода. Если не будет, я приму ваш ответ. Кстати, я не знал, что значением по умолчанию для string.split при передаче значения null является пробел. Прямо сейчас я использую подход Linq, чтобы получить атрибут schemaLocation, а затем каким-то образом извлечь путь. Однако метод разбиения, который вы написали, лучше, чем моя попытка регулярного выражения. Однако это не удастся, если в пути есть пробелы. Благодарю.
  • 0
    Пробелы не должны существовать в пути, если он находится в schemaLocation или noNamespaceSchemaLocation поскольку действительная схема URI требует их экранирования (до %20 ). Таким образом, URL-адрес, такой как: file:///c:/My Directory/file.xsd , будет включен как file:///c:/My%20Directory/file.xsd . Пространства также важны в schemaLocation так как они используются для отделения каждой схемы от ее местоположения, а также пар схема / местоположение.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню