1

私は XPath に慣れていないので、ファイルから 3 つの値 (schemaversion、title、および description) を選択するだけのガイダンスを探しています。

Xpath 式は、と//title/langstringから名前間隔情報を取り除いた場合にのみ、要素の値と一致します。<manifest><lom>

これらの値のコンテンツを検索する正しい方法は何ですか?

単体テスト:

[Test]
public void TitleIsNotNull()
{
  var manifestManager = new ManifestManager("imsmanifest.xml");
  // Code which initializes object and calls GetTitle() is encapsulated.
  Assert.IsNotNullOrEmpty(manifestManager.Title);
}

テスト中のシステム:

private string GetTitle()
{
  var document = XElement.Parse(_contents);
  const string XpathExpression = "//title/langstring";
  return (string)document.XPathSelectElement(XpathExpression);
}

_内容(抜粋):

<?xml version="1.0" encoding="utf-8"?>
<manifest xsi:schemaLocation="http://www.imsproject.org/xsd/imscp_rootv1p1p2
  imscp_rootv1p1p2.xsd 
  http://www.imsglobal.org/xsd/imsmd_rootv1p2p1 imsmd_rootv1p2p1.xsd 
  http://www.adlnet.org/xsd/adlcp_rootv1p2 adlcp_rootv1p2.xsd" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:adlcp="http://www.adlnet.org/xsd/adlcp_rootv1p2" 
  xmlns="http://www.imsproject.org/xsd/imscp_rootv1p1p2" 
  version="1.0"
  identifier="ExampleIdGoesHere">
  <metadata>
    <schema>ADL SCORM</schema>
    <schemaversion>1.2</schemaversion>
    <lom xsi:schemaLocation="http://www.imsglobal.org/xsd/imsmd_rootv1p2p1
               imsmd_rootv1p2p1.xsd" 
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
               xmlns="http://www.imsglobal.org/xsd/imsmd_rootv1p2p1">
        <general>
            <title>
                <langstring xml:lang="x-none">Example title goes here.</langstring>
            </title>
            <description>
                <langstring xml:lang="x-none">Example description goes here.</langstring>
            </description>
        </general>
    </lom>
  </metadata>

Steven Doggart のソリューションに基づくコードの微調整

//改訂

private string GetTitle()
{
  var xmlReader = GetXmlReader();
  var document = XElement.Load(xmlReader);
  var xmlNamespaceManager = GetXmlNamespaceManager(xmlReader);
  const string XpathExpression = "//y:title/y:langstring";
  return (string)document.XPathSelectElement(XpathExpression, xmlNamespaceManager);
}

//プライベート ヘルパー

    private XmlReader GetXmlReader()
    {
        var contents = new StringReader(_contents);
        var xmlReader = XmlReader.Create(contents);
        return xmlReader;
    }

    private XmlNamespaceManager GetXmlNamespaceManager(XmlReader xmlReader)
    {
        if (xmlReader.NameTable != null)
        {
            var xmlNamespaceManager = new XmlNamespaceManager(xmlReader.NameTable);
            xmlNamespaceManager.AddNamespace("x", "http://www.imsproject.org/xsd/imscp_rootv1p1p2");
            xmlNamespaceManager.AddNamespace("y", "http://www.imsglobal.org/xsd/imsmd_rootv1p2p1");
            return xmlNamespaceManager;
        }

        return null;
    } 
4

1 に答える 1

0

あなたが抱えている問題は、選択しようとしている要素が実際には特定の名前空間に属しているが、選択時に名前空間を指定していないことです。title要素と要素はどちらもデフォルトのlangstring名前空間に属しています。XML ドキュメントでは、デフォルトの名前空間は として定義されてい"http://www.imsproject.org/xsd/imscp_rootv1p1p2"ます。XPath では、デフォルトの名前空間を指定する方法はありません。名前空間を指定しない場合、名前空間がまったくないという意味であると常に想定されます。したがって、その要素を選択するには、次のように名前空間を明示的に指定する必要があります。

XmlNamespaceManager namespaceManager = new XmlNamespaceManager(nameTable);
namespaceManager.AddNamespace("x", "http://www.imsproject.org/xsd/imscp_rootv1p1p2");
const string XpathExpression = "//x:title/x:langstring";
return (string)document.XPathSelectElement(XpathExpression, namespaceManager);

ただし、トリックは、XmlNameTableを に与えることXmlNamespaceManagerです。残念ながら、XElementクラスはドキュメントの を取得する方法を提供していないため、次のように、それを提供できる をXmlNameTable介してロードするのが最善の策です。XmlReader

XmlReader reader = XmlReader.Create(new StringReader(_contents));
XElement document = XElement.Load(reader);
XmlNamespaceManager namespaceManager = new XmlNamespaceManager(reader.NameTable);
namespaceManager.AddNamespace("x", "http://www.imsproject.org/xsd/imscp_rootv1p1p2");
const string XpathExpression = "//x:title/x:langstring";
return (string)document.XPathSelectElement(XpathExpression, namespaceManager);

XmlDocumentまたは、名前空間を扱うときに少し簡単な方を使用することもできます。または、XPath の代わりに LINQ を使用して要素を選択することもできます。

于 2013-08-30T14:06:10.837 に答える