使用XamlXmlReader从X行读取Xaml中的Y行

时间:2014-01-23 15:23:12

标签: xml xaml xmlreader xamlreader

我正在尝试调用签名看起来像

的第三方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) 什么是IXamlLineInfoXamlXmlReaderSettings.ProvideLineInfo

由于

1 个答案:

答案 0 :(得分: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的任何内容。