2

我正在尝试调用签名看起来像的第三方 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,它从 [line 7, column 12] 加载到 [line 9, column 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关于什么?

谢谢

4

1 回答 1

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 中的任何内容。

于 2014-02-03T01:21:51.040 回答