<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mpeg:DASH:schema:MPD:2011" xmlns:yt="http://youtube.com/yt/2012/10/10" xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd" minBufferTime="PT1.500S" profiles="urn:mpeg:dash:profile:isoff-main:2011" type="static" mediaPresentationDuration="PT26246.117S">
<Period>
...
</Period>
</MPD>
private void ParseDashManifest(string dashManifestString)
{
XmlDocument xml = new XmlDocument();
xml.LoadXml(dashManifestString);
XmlNode period = xml.DocumentElement.SelectSingleNode("Period"); //null
foreach (XmlNode node in period)
{
System.Diagnostics.Debug.WriteLine(node.Name);
}
}
Как найти нод Period
без прохода циклом? Должен же быть стандартный метод для этого. Даже в Delphi он есть.
AlexP
(Alex P.)
14.Март.2021 08:24:54
#2
BlackRain666:
//null
Должно работать, наверно что-то с XML.
using System;
using System.Xml;
public class Program
{
public static void Main()
{
XmlDocument xml = new XmlDocument();
xml.LoadXml(@"<?xml version=""1.0"" encoding=""UTF-8""?>
<MPD>
<Period> <Child /> </Period>
</MPD>");
XmlNode period = xml.DocumentElement.SelectSingleNode("Period");
foreach (XmlNode child in period)
{
Console.WriteLine(child.Name);
}
}
}
https://dotnetfiddle.net/38Q8hY
AlexP
(Alex P.)
14.Март.2021 08:38:00
#3
А, тут же неймспейс.
Надо либо как-то с помощью XmlNamespaceManager Class (System.Xml) | Microsoft Docs (передать в SelectSingleNode
вторым параметром), либо так
using System;
using System.Xml;
public class Program
{
public static void Main()
{
XmlDocument xml = new XmlDocument();
xml.LoadXml(@"<?xml version=""1.0"" encoding=""UTF-8""?>
<MPD xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns=""urn:mpeg:DASH:schema:MPD:2011"" xmlns:yt=""http://youtube.com/yt/2012/10/10"" xsi:schemaLocation=""urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd"">
<Period> <Child /> </Period>
</MPD>");
XmlNode period = xml.DocumentElement.SelectSingleNode("//*[local-name()='Period']");
foreach (XmlNode child in period)
{
Console.WriteLine(child.Name);
}
}
}
Ну или как-нибудь удалить атрибут xmlns
.
AlexP:
наверно что-то с XML.
Не может быть. На Delphi работает.
AlexP
(Alex P.)
14.Март.2021 08:44:03
#5
Видимо библиотека в Дельфи не поддерживает неймспейсы.
AlexP
(Alex P.)
14.Март.2021 08:47:37
#7
Я знаю, что есть ноды и аттрибуты. А неймспейс (namespace) это что? Из википедии нифига не понял.
Почему и как эти неймспейсы мешают поиску нода?
каким образом он на что-то влияет? Ничего же не меняется.
и почему с такой фигнёй ("//*[local-name()='Period']")
работает?
AlexP
(Alex P.)
14.Март.2021 10:25:23
#9
XML Namespaces
BlackRain666:
Ничего же не меняется.
Тут ко всем элементам внутри добавится неймспейс, так что его полное имя больше не Period
.
Через XmlNamespaceManager можно объявить неймспейсы для XPath и использовать их в запросе.
https://stackoverflow.com/a/40796315/964478
var nsmgr = new XmlNamespaceManager(xml.NameTable);
nsmgr.AddNamespace("u", "urn:mpeg:DASH:schema:MPD:2011");
XmlNode period = xml.DocumentElement.SelectSingleNode("u:Period", nsmgr);
local-name()
возвращает имя без неймспейса.
https://developer.mozilla.org/en-US/docs/Web/XPath/Functions/local-name
Боюсь даже спрашивать, кто и зачем придумывает такие удобства…
В JSON’ах же таких удобств нет
AlexP
(Alex P.)
14.Март.2021 11:50:26
#11
По первой ссылке был же пример зачем. Как и любые неймспейсы, для решения конфликтов имен.
JSON проще, но там есть другие проблемы, например, с тем, что есть куча разных спецификаций и парсеров конфликтующих друг с другом. Забавные факты о языках программирования/библиотеках/технологиях - #14 от пользователя AlexP
И в некотором он уж слишком сильно ограничен, нельзя даже добавить коммент/закомментить строку, что бывает полезно в конфигах и т.п.
что-то вообще странное происходит
я читаю отсюда
а получаю отсюда
private void ParseDashManifest(string dashManifestString)
{
XmlDocument xml = new XmlDocument();
xml.LoadXml(dashManifestString);
XmlNode period = xml.DocumentElement.SelectSingleNode("//*[local-name()='Period']");
foreach (XmlNode nodeAdaptationSet in period)
{
string mimeType = nodeAdaptationSet.Attributes["mimeType"].Value;
string[] mimeTypeSplit = mimeType.Split('/');
if (mimeType.Contains("video"))
{
foreach (XmlNode node in nodeAdaptationSet)
{
if (node.Name.Equals("Representation"))
{
YouTubeVideoFile videoFile = new YouTubeVideoFile();
videoFile.dashManifestUrls = new List<string>();
//здесь 133, всё прекрасно, птички поют
videoFile.formatId = int.Parse(node.Attributes["id"].Value);
videoFile.width = int.Parse(node.Attributes["width"].Value);
videoFile.height = int.Parse(node.Attributes["height"].Value);
videoFile.bitrate = int.Parse(node.Attributes["bandwidth"].Value);
videoFile.fps = int.Parse(node.Attributes["frameRate"].Value);
videoFile.mimeCodecs = node.Attributes["codecs"].Value;
videoFile.mimeType = mimeType + "; codecs=\"" + videoFile.mimeCodecs + "\"";
videoFile.mimeExt = mimeTypeSplit[1];
videoFile.fileExtension = videoFile.mimeExt == "mp4" ? "m4v" : videoFile.mimeExt;
videoFile.isDashManifest = true;
videoFile.dashManifestUrls = new List<string>();
//а здесь получается ссылка на файл с ID 139
XmlNode nodeBaseUrl = node.SelectSingleNode("//*[local-name()='BaseURL']");
string baseUrl = nodeBaseUrl.InnerText;
//дальнейшее уже бессмысленно
XmlNode nodeSegmentList = node.SelectSingleNode("//*[local-name()='SegmentList']");
XmlNode nodeInitialization = nodeSegmentList.SelectSingleNode("//*[local-name()='Initialization']");
if (nodeInitialization != null)
{
string sourceUrl = nodeInitialization.Attributes["sourceURL"].Value; //тут range/0-640
videoFile.dashManifestUrls.Add(baseUrl + sourceUrl);
}
foreach (XmlNode nodeSegment in nodeSegmentList)
{
if (nodeSegment.Name.Equals("SegmentURL"))
{
string segmentUrl = baseUrl + nodeSegment.Attributes["media"].Value;
videoFile.dashManifestUrls.Add(segmentUrl);
}
}
videoFiles.Add(videoFile);
}
}
}
else
if (mimeType.Contains("audio"))
{
}
}
}
AlexP
(Alex P.)
14.Март.2021 16:16:22
#15
По-моему //
всегда с корня документа начинает, надо .
добавить, чтобы искать от текущего.
И чтобы искать среди прямых потомков (один уровень) можно использовать /
.
node.SelectSingleNode("./*[local-name()='BaseURL']")