0

XPathを使用して特定のxml要素(要素Aと呼びます)を見つけてから、要素Aによって参照される別の要素(要素B)を見つける必要があるアプリがあります(実際にはあります)。例:

public static void Main(string[] args)
    {
        var s = @"
<Root>
    <Start refId = ""5""/>
    <Start refId = ""6""/>
    <Item id = ""5""/>
    <Item id = ""6""/>
</Root>
";

        var doc = new XmlDocument();
        using (var sr = new StringReader(s))
        {
            doc.Load(sr);
        }

        XmlNode nodeA = doc.SelectNodes(@"Root/Start[1]")[0];
        var selected = nodeA.SelectNodes(@"/Root/Item[@id = @refId]");
    }

ここで、nodeAは私が見つけることができるノードAです。選択されているのは、見つからないノードBのコレクションです。私の問題は[@id=@refId]にあり、そこから開始したnodeAに戻り、その属性 "refId"の値を取得したいのですが、方法がわかりません。これを達成することは可能ですか?

4

2 に答える 2

1

あなたはこのようにそれを行うことができます:

XmlNode nodeA = doc.SelectNodes(@"Root/Start[1]")[0];
var selected = nodeA.SelectNodes("/Root/Item[@id = " + nodeA.Attributes["refId"].Value + "]");
于 2013-03-21T11:17:59.763 に答える
1

編集:コメントで以下に説明することを達成するために私が見ることができる唯一の方法は、LINQ to XML、XPath変数を使用するか、独自のcurrent()関数を定義することです。XPath変数と現在の関数は、それらを処理するために独自のクラスを作成する必要があるため、少し面倒ですが、これらの比較的単純なジェネリッククラスを使用できます。

public class VariableContext : XsltContext
{
    IXPathNavigable CurrentNode;

    Dictionary<string, object> Values = new Dictionary<string, object>();
    public void SetValue(string name, object value)
    {
        Values[name] = value;
    }
    public void SetCurrentNode(IXPathNavigable currentNode)
    {
        CurrentNode = currentNode;
    }

    public override int CompareDocument(string baseUri, string nextbaseUri)
    {
        throw new NotImplementedException();
    }

    public override bool PreserveWhitespace(System.Xml.XPath.XPathNavigator node)
    {
        return false;
    }

    public override IXsltContextFunction ResolveFunction(string prefix, string name, System.Xml.XPath.XPathResultType[] ArgTypes)
    {
        if (name.Equals("current"))
        {
            return new CurrentFunction(CurrentNode);
        }
        throw new NotImplementedException();
    }

    public override IXsltContextVariable ResolveVariable(string prefix, string name)
    {
        object value;
        if (Values.TryGetValue(name, out value))
        {
            return new ContextVariable(name, value);
        }
        throw new ApplicationException("Unknown variable: " + name);
    }

    public override bool Whitespace
    {
        get { return false; }
    }
}

public class ContextVariable : IXsltContextVariable
{
    private string m_name;
    private object m_parameter;

    public ContextVariable(string name, object parameter)
    {
        m_name = name;
        m_parameter = parameter;

        IXPathNavigable navigable = m_parameter as IXPathNavigable;
        if (navigable != null)
        {
            m_parameter = navigable.CreateNavigator().Select(".");
        }
    }

    #region IXsltContextVariable Members

    public object Evaluate(XsltContext xsltContext)
    {
        return m_parameter;
    }

    public bool IsLocal
    {
        get { return true; }
    }

    public bool IsParam
    {
        get { return true; }
    }

    public XPathResultType VariableType
    {
        get
        {
            return XPathResultType.Any;
        }
    }

    #endregion
}

public class CurrentFunction : IXsltContextFunction
{
    private XPathNodeIterator CurrentNodeIterator;
    internal CurrentFunction(IXPathNavigable currentNode)
    {
        if (currentNode != null)
        {
            CurrentNodeIterator = currentNode.CreateNavigator().Select(".");
        }
    }

    public XPathResultType[] ArgTypes
    {
        get { return new XPathResultType[0]; }
    }

    public object Invoke(XsltContext xsltContext, object[] args, 
                         XPathNavigator docContext)
    {
        if (CurrentNodeIterator == null)
        {
            throw new ApplicationException("Current node is not set.");
        }
        return CurrentNodeIterator;
    }

    public int Maxargs
    {
        get { return 0; }
    }

    public int Minargs
    {
        get { return 0; }
    }

    public XPathResultType ReturnType
    {
        get { return XPathResultType.NodeSet; }
    }
}

どこかでそれを定義したら、次のことができます。

VariableContext vc = new VariableContext();
XmlNode nodea = doc.SelectSingleNode("Root/Start[1]");
vc.SetValue("a", nodea);
XmlNodeList selected = doc.SelectNodes("/Root/Item[@id = $a/@refId]", vc);

または、カスタム定義のcurrent()関数を使用します。

VariableContext vc2 = new VariableContext();
XmlNode nodea2 = doc.SelectSingleNode("Root/Start[1]");
vc2.SetCurrentNode(nodea2);
XmlNodeList selected2 = doc.SelectNodes("/Root/Item[@id = current()/@refId]", vc2);
PrintNodeList(selected2);

ワーキングイデオネ:http://ideone.com/7wsQ46

于 2013-03-21T11:22:12.360 に答える