我已經使用xml.Load("myfile.xml");where xmlis of type加載了以下 XML 檔案XmlDocument:
<?xml version="1.0" encoding="ISO-8859-1"?>
<DTE xmlns="http://www.sii.cl/SiiDte" version="1.0">
<Documento ID="E000000005T033F0114525415">
<Encabezado>
<IdDoc>
<TipoDTE>33</TipoDTE>
<Folio>114525415</Folio>
<FchEmis>2021-11-02</FchEmis>
<FmaPago>1</FmaPago>
<FchVenc>2021-11-02</FchVenc>
</IdDoc>
</Encabezado>
</Documento>
</DTE>
我怎樣才能得到Folio節點?
我試過:
xml.DocumentElement.SelectSingleNode("/DTE/Documento/Encabezado/IdDoc/Folio");
xml.DocumentElement.SelectNodes("DTE/Documento/Encabezado/IdDoc/Folio")
xml.DocumentElement.SelectSingleNode("//DTE/Documento/Encabezado/IdDoc/Folio");
xml.DocumentElement.SelectSingleNode("/Documento/Encabezado/IdDoc/Folio");
xml.DocumentElement.SelectSingleNode("Documento/Encabezado/IdDoc/Folio");
xml.DocumentElement.SelectSingleNode("/Encabezado/IdDoc/Folio");
xml.DocumentElement.SelectNodes("/DTE/Documento/Encabezado/IdDoc/Folio")
當我除錯時,xml.DocumentElement我看到該元素是DTE如此,我認為xml.DocumentElement.SelectSingleNode("Documento/Encabezado/IdDoc/Folio")應該這樣做。
當我得到xml.DocumentElement.FirstChild我得到Documento節點。
隨著xml.DocumentElement.FirstChild.FirstChild我得到Encabezado節點。
隨著xml.DocumentElement.FirstChild.FirstChild.FirstChild我得到IdDoc節點。
如果我使用xml.DocumentElement.FirstChild.FirstChild.FirstChild.SelectSingleNode("Folio"),回傳值為空。
如果我使用xml.DocumentElement.FirstChild.FirstChild.FirstChild.ChildNodes,我會得到 5 個元素。
然后我可以xml.DocumentElement.FirstChild.FirstChild.FirstChild.ChildNodes[1].InnerText用來獲取Folio價值。
我可以遍歷 XML,但是如何直接獲取元素?
謝謝海梅
uj5u.com熱心網友回復:
最好將LINQ to XML API 用于您的任務。自 2007 年以來,它在 .Net Framework 中可用。
提供的 XML 具有默認命名空間。它需要宣告和使用,否則無法找到任何 XML 元素。
C#
void Main()
{
const string filename = @"e:\Temp\jstuardo.xml";
XDocument xdoc = XDocument.Load(filename);
XNamespace ns = xdoc.Root.GetDefaultNamespace();
string Folio = xdoc.Descendants(ns "Folio")
.FirstOrDefault()?.Value;
Console.WriteLine("Folio='{0}'", Folio);
}
輸出
Folio='114525415'
uj5u.com熱心網友回復:
您可以嘗試使用如下的 Xpath:
XmlDocument doc = new XmlDocument();
doc.Load("myfile.xml");
var node= doc.SelectSingleNode("Documento/Encabezado/IdDoc/[Folio='"114525415"']");
uj5u.com熱心網友回復:
有幾種方法可以解決您的問題。
所以,我們有我們的 XML:
const string MyXML = @"<?xml version=""1.0"" encoding=""ISO-8859-1""?>
<DTE xmlns=""http://www.sii.cl/SiiDte"" version=""1.0"">
<Documento ID=""E000000005T033F0114525415"">
<Encabezado>
<IdDoc>
<TipoDTE>33</TipoDTE>
<Folio>114525415</Folio>
<FchEmis>2021-11-02</FchEmis>
<FmaPago>1</FmaPago>
<FchVenc>2021-11-02</FchVenc>
</IdDoc>
</Encabezado>
</Documento>
</DTE>";
我們需要獲取Folio節點(確切地說是節點,而不僅僅是值)。我們可以用:
Xml 命名空間管理器:
通過 XPath 中的 XML 命名空間 (xmlns) 別名查找后代節點:
// Creating our XmlDocument instance
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(MyXML);
// Initializing XmlNamespaceManager and providing our xmlns with 'SiiDte' alias:
var xmlNamespaceManager = new XmlNamespaceManager(xmlDocument.NameTable);
xmlNamespaceManager.AddNamespace("SiiDte", "http://www.sii.cl/SiiDte");
// Declaring our simple shiny XPath:
var xPath = "descendant::SiiDte:Folio";
// If we need single (first) element:
var folio = xmlDocument.DocumentElement.SelectSingleNode(xPath, xmlNamespaceManager);
// If we need all Folios:
var folios = xmlDocument.DocumentElement.SelectNodes(xPath, xmlNamespaceManager);
XDocument 及其后代:
從System.Xml.Linq命名空間及其XDocument類中,僅通過標簽名稱查找后代節點<Folio>:
// If we need single (first) element:
var folio = XDocument.Parse(MyXML)
.Descendants()
.FirstOrDefault(x => x.Name.LocalName == "Folio");
// Add System.Linq using to access FirstOrDefault extension method
// If we need all Folios - just replacing FirstOrDefault with Where extension method:
var folios = XDocument.Parse(MyXML)
.Descendants()
.Where(x => x.Name.LocalName == "Folio"); // and .ToList() if you need
// Or we can use also our XML namespace to filter Descendants:
var ns = (XNamespace)"http://www.sii.cl/SiiDte";
var folios = XDocument.Parse(MyXML).Descendants(ns "Folio");
反序列化:
不使用 XML 或節點操作,而是使用一些類(例如DTE),它代表您的 XML 模式。我不確定我是否完全理解您的 XML 結構,但無論如何都可以使用它作為示例。
所以我們創建了我們的類,它們是我們的 XML 的表示:
[Serializable, XmlRoot(ElementName = nameof(DTE), Namespace = "http://www.sii.cl/SiiDte")]
public class DTE
{
[XmlAttribute("version")]
public string Version { get; set; }
[XmlElement(nameof(Documento))]
public List<Documento> Documentacion { get; set; }
}
[Serializable]
public class Documento
{
[XmlAttribute(nameof(ID))]
public string ID { get; set; }
[XmlElement(nameof(Encabezado))]
public Encabezado Encabezado { get; set; }
}
[Serializable]
public class Encabezado
{
[XmlElement(nameof(IdDoc))]
public IDDoc IdDoc { get; set; }
}
[Serializable]
public class IDDoc
{
[XmlElement(nameof(TipoDTE))]
public int TipoDTE { get; set; }
[XmlElement(nameof(Folio))]
public long Folio { get; set; }
[XmlElement(nameof(FchEmis))]
public DateTime FchEmis { get; set; }
[XmlElement(nameof(FmaPago))]
public int FmaPago { get; set; }
[XmlElement(nameof(FchVenc))]
public DateTime FchVenc { get; set; }
}
現在我們可以輕松地DTE使用XmlSerializer類及其Deserialize方法創建我們的物件:
// Declaring our DTE object
var dte = (DTE)null;?
using (var reader = new StringReader(MyXML))
{
dte = (DTE)new XmlSerializer(typeof(DTE)).Deserialize(reader);
}
現在我們可以得到類的Folio屬性IdDoc,它是Encabezado類的屬性,它又是Documento類的屬性。記住可能的null結果讓我們使用,例如null-propagation:
var folio = dte?.Documentacion.FirstOrDefault()?.Encabezado?.IdDoc?.Folio;
As Documentacionis a List<Documento>- 我們再次使用FirstOrDefault(也可以使用ElementAtOrDefault(0))來“模仿” SelectSingleNode。對于Folios我們可以使用的所有內容Select(也使用多傳播):
var folios = dte?.Documentacion.Select(x => x?.Encabezado?.IdDoc?.Folio);
當然,我們可以根據需要編輯屬性或添加新屬性:
// Edit
if (dte?.Documentacion.FirstOrDefault() is Documento documento)
documento.Encabezado.IdDoc.Folio = 112233445566;
// or create and add new
var newDocumento = new Documento
{
ID = "SomeID",
Encabezado = new Encabezado
{
IdDoc = new IDDoc
{
TipoDTE = 123,
Folio = 112233445566,
FmaPago = 1,
FchEmis = DateTime.Now,
FchVenc = DateTime.Now.AddDays(1)
}
}
};
dte.Documentacion.Add(newDocumento);
最后使用序列化保存回 XML 檔案。這里變得可用我們的類和屬性屬性(例如[Serializable],[XmlElement]等),它指定每個屬性應該如何命名或在 XML 中表示:
using (var xmlWriter = XmlWriter.Create("My.xml",
new XmlWriterSettings
{
Encoding = Encoding.GetEncoding("ISO-8859-1"),
Indent = true
}))
{
// We remove default XSI, XSD namespaces and leave only our custom:
var xmlSerializerNamespaces = new XmlSerializerNamespaces();
xmlSerializerNamespaces.Add("", "http://www.sii.cl/SiiDte");
// and saving our DTE object to XML file.
xmlSerializer.Serialize(xmlWriter, dte, xmlSerializerNamespaces);
}
評論
當然,FileStream如果需要,XML 字串的決議可以替換為加載 XML 檔案(按s)。當然,您可以使用其他屬性編輯 DTE(和子)類,并將它們標記為 XML 屬性或 XML 元素,或者使用XmlArray和XmlArrayItem屬性創建集合- 無論如何,這取決于您的需要。還要注意nullXML 節點或其值,并注意它,例如,Nullable<T>(例如long?, DateTime?)、IsNullableXML 屬性的屬性和屬性設定器中的某種值驗證:
private long _folio;
[XmlElement(nameof(Folio), IsNullable = true)]
public long? Folio
{
get => _folio;
set => _folio = value ?? 0L; // Null-coalescing with default fallback value of 0L
}
希望它對您未來的目的有所幫助。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/383955.html
