Чтение от строки X до строки Y из Xaml с помощью XamlXmlReader
Я пытаюсь вызвать метод API третьей части, подпись которого выглядит
object Load(XamlXmlReader reader);
Затем с учетом этого образца XAML
<Foo xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:barns="clr-namespace:Bar;assembly=Bar"
Property="Value">
<Root>
<Element1 />
<Element2>
<SubElement>
<barns:Sample />
</SubElement>
</Element2>
</Root>
</Foo>
Мне нужно, чтобы предоставить API XamlXmlReader, который загружается, скажем, с [строка 7, столбец 12] до [строка 9, столбец 25]
<SubElement>
<barns:Sample />
</SubElement>
Окончательный Xaml, прочитанный читателем, должен быть
<Foo xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:barns="clr-namespace:Bar;assembly=Bar"
Property="Value">
<SubElement>
<barns:Sample />
</SubElement>
</Foo>
Есть ли функция, которая делает это чтение? Если мне нужно накатить свои собственные предложения или ресурсы, помимо создания другого файла с этим содержимым вручную из необработанной строки, это может помочь?(Я не знаком с XamlXmlReader) IXamlLineInfo
а также XamlXmlReaderSettings.ProvideLineInfo
около?
Спасибо
1 ответ
Это решение, которое я нашел, оно использует linq to XML, не стесняйтесь предлагать улучшения.
public static XDocument CreateDocumentForLocation(Stream stream, Location targetLocation)
{
stream.Seek(0, 0);
XElement root;
List<XNode> nodesInLocation;
XNamespace x = "http://schemas.microsoft.com/winfx/2006/xaml";
using (var xmlReader = XmlReader.Create(stream, new XmlReaderSettings {
CloseInput = false }))
{
XDocument doc = XDocument.Load(xmlReader,
LoadOptions.SetLineInfo | LoadOptions.PreserveWhitespace);
root = doc.Root;
nodesInLocation = doc.Root.DescendantNodes()
.Where(node => IsInside(node, targetLocation))
.ToList();
}
root.RemoveNodes();
XDocument trimmedDocument = XDocument.Load(root.CreateReader());
trimmedDocument.Root.Add(nodesInLocation.FirstOrDefault());
return trimmedDocument;
}
public static bool IsInside(XNode node, Location targetLocation)
{
var lineInfo = (IXmlLineInfo)node;
return (lineInfo.LineNumber > targetLocation.StartLine && lineInfo.LineNumber < targetLocation.EndLine) // middle
|| (lineInfo.LineNumber == targetLocation.StartLine && lineInfo.LinePosition >= targetLocation.StartColumn) // first line after start column
|| (lineInfo.LineNumber == targetLocation.EndLine && lineInfo.LinePosition <= targetLocation.EndColumn); // last line until last column
}
Мне нужно было вставить некоторые другие элементы в XML в моем приложении. Это основной фрагмент, вы сможете использовать linq to xml для простого запроса всего, что хотите добавить в окончательный XML.