xmlNameSpaceManager   zodpovězená otázka

VB.NET, XML

Dobrý den,

potřeboval bych poradit s následujícím problémem ve Visual Basicu 2010 Express.

Mám xml soubor, který začíná takto:

<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns:sdl="http://sdl.com/FileTypes/SdlXliff/1.0" version="1.2" sdl:version="1.0" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file original="cesta_k_souboru1">nějaký obsah</file>
<file original="cesta_k_souboru2">nějaký obsah</file>
.
.
.

Pak mám proceduru, která by měla s tímto souborem pracovat. Zasekl jsem se hned na začátku, když jsem po té proceduře chtěl, aby mi spočítala, kolikrát se v souboru vyskytuje element <file>.

Procedura v tuto chvíli vypadá zhruba takto:

xmlSourceDocument.XmlResolver = Nothing
xmlSourceDocument.Load(inputFileName)

'Create an XmlNamespaceManager for resolving namespaces.
Dim nsmgr As XmlNamespaceManager = New XmlNamespaceManager(xmlSourceDocument.NameTable)
        nsmgr.AddNamespace("sdl", "http://sdl.com/FileTypes/SdlXliff/1.0")

Dim fileCount As Integer = xmlSourceDocument.SelectNodes("xliff/file", nsmgr).Count

Problém je, že proměnná fileCount mi pořád ukazuje hodnotu 0.

Když ovšem použiju zdrojový soubor, který v názvech elementů nepoužívá dvojtečku a když z úvodního tagu xliff vyházím ty názvové prostory, vše se spočítá korektně.

Můžete mi prosím poradit, v čem je problém?

Předem děkuji

Vladimír Vašek

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Jo tak tady jsem taky narazil :)

http://www.vbnet.cz/forum-tema--5806-xel...

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Dobrý den,

děkuji za odpověď, nicméně pořád dělám něco špatně.

Tady je současný kód:

Imports System.IO
Imports System.Xml
Imports System.Text.RegularExpressions
Imports System.Text
Imports <xmlns="urn:oasis:names:tc:xliff:document:1.2">
Imports <xmlns:sdl="http://sdl.com/FileTypes/SdlXliff/1.0">


Public Class SDLXLIFFUnmergerMain

    Dim inputFileName As String
    Dim xmlSourceDocument As XmlDocument = New XmlDocument()
    Dim xmlTargetDocument As New XmlDocument()
    Dim outputFileName As String
    Dim outputDirectory As String
    Dim outputSDLXLIFFFileName As String
    Dim methodStart As New TimeSpan
    Dim methodEnd As New TimeSpan


    Private Sub UnmergeFiles()

        methodStart = DateTime.Now.TimeOfDay


        xmlSourceDocument.XmlResolver = Nothing
        xmlSourceDocument.Load(inputFileName)

        'Create an XmlNamespaceManager for resolving namespaces.
        Dim nsmgr As XmlNamespaceManager = New XmlNamespaceManager(xmlSourceDocument.NameTable)
        nsmgr.AddNamespace("", "urn:oasis:names:tc:xliff:document:1.2")
        nsmgr.AddNamespace("sdl", "http://sdl.com/FileTypes/SdlXliff/1.0")

        Dim fileCount As Integer = xmlSourceDocument.SelectNodes("xliff/file", nsmgr).Count

        methodEnd = DateTime.Now.TimeOfDay
    End Sub

Můžete mi prosím říct, co dělám špatně?

Předem moc díky

Vladimír Vašek

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tohle by Vám mohlo pomoci. Nepoužívám XmlDocument, ale XDocument (System.Xml.Linq), což je novější a flexibilnější implementace XML v .NET frameworku designovaná s ohledem na možnost pracovat s prvky pomocí LINQ.

http://msdn.microsoft.com/en-us/library/... XDocument na MSDN

http://msdn.microsoft.com/en-us/library/... Axis Properties - způsob, jak vybírat prvky v XML pomocí speciální syntaxe jazyka

Imports <xmlns="urn:oasis:names:tc:xliff:document:1.2">
Imports <xmlns:sdl="http://sdl.com/FileTypes/SdlXliff/1.0">
Module Module1
  Sub Main()
    Dim doc =
      <?xml version="1.0" encoding="utf-8"?>
      <xliff xmlns:sdl="http://sdl.com/FileTypes/SdlXliff/1.0" version="1.2" sdl:version="1.0" xmlns="urn:oasis:names:tc:xliff:document:1.2">
        <file original="cesta_k_souboru1" source-language="en-us" datatype="x-sdlfilterframework2" target-language="cs-CZ"/>
        <file original="cesta_k_souboru2" source-language="en-us" datatype="x-sdlfilterframework2" target-language="cs-CZ"/>
        <file original="cesta_k_souboru3" source-language="en-us" datatype="x-sdlfilterframework2" target-language="cs-CZ"/>
        <file original="cesta_k_souboru4" source-language="en-us" datatype="x-sdlfilterframework2" target-language="cs-CZ"/>
      </xliff>
    Dim count = doc.<xliff>.<file>.Count()
    Console.WriteLine(count)
    Console.ReadLine()
  End Sub
End Module
nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Dobrý den,

děkuju za odpověď. Asi by mi to pomohlo, ale už mám poměrně dost kódu napsaného s využitím třídy XmlDocument. Jako začátečníkovi mi už jen toto dalo dost práce a rád bych zatím u tohoto modelu zůstal, než se pustím do dalších neprobádaných vod.

Jen bych rád věděl, co dělám špatně, potřebuji ve zdrojovém xml dělat pomocí XmlDocument více operací než jen počítat uzly, a nefunguje žádná. V XML bez jmenných prostorů vše funguje jak má.

Dle informací z všemožných zdrojů mám pocit, že je můj kód napsaný správně (z pohledu třídy XmlDocument). Tak v čem je zakopaný pes?

Předem díky za další odpovědi

Vladimír Vašek

nahlásit spamnahlásit spam 0 odpovědětodpovědět
Imports System.Xml

Module Module1
  Sub Main()
    Dim doc = New XmlDocument()
    doc.Load("C:/xliff.xml")

    Dim nm = New XmlNamespaceManager(doc.NameTable)
    nm.AddNamespace("def", "urn:oasis:names:tc:xliff:document:1.2")
    nm.AddNamespace("sdl", "http://sdl.com/FileTypes/SdlXliff/1.0")

    ' Prohledá všechy uzly na všech úrovních 
    ' (ve Vámi poskytnutých datech je pouze jedna 
    ' úroveň dceřinných prvků, takže shodné se SelectNodes)
    Console.WriteLine(doc.GetElementsByTagName("file").Count)

    ' Pomocí XPath vybereme potomky <xliff> jména <file> z výchozího ns
    ' Nebo všechny prvky v dokumentu jména <file>: //def:file
    ' http://www.w3schools.com/xpath/default.asp
    ' http://interval.cz/clanky/zaklady-jazyka-xpath/
    Console.WriteLine(doc.SelectNodes("def:xliff/def:file", nm).Count)

    Console.ReadLine()
  End Sub
End Module

Jak vidíte, 2× zaregistrovávám výchozí namespace, jednou pod prefixem String.Empty, což by mělo znamenat výchozí prefix, a podruhé pod prefixed "def:". Z nějakého důvodu mi to se String.Empty nešlo, XPath nic nevybralo. Možná rozlousknete, proč to tak je, já jsem jako hotfix ten namespace pojmenoval "def:" a přidal ho 2×, to ničemu nevadí. :)

Edit: Podle http://stackoverflow.com/questions/42716... je ve specifikaci uvedeno, že prázdný řetězec neznamená výchozí namespace, ale prázdný namespace. Kadžý namespace se tedy musí nějak jmenovat, i výchozí namespace XML dokumentu. Proti dokumentaci XPath jsem to neověřoval, ale chování kódu tomu odpovídá. V tom byl tedy nejspíše Váš problém.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Dobrý den, díky moc, už to funguje. Toto se mi tedy vygooglovat nepodařilo.

Abych to tedy shrnul, nakonec není nutné používat na začátku kódu

Imports <xmlns="urn:oasis:names:tc:xliff:document:1.2">
Imports <xmlns:sdl="http://sdl.com/FileTypes/SdlXliff/1.0"

(aspoň mně to bez toho funguje) a při definici xmlNameSpaceManageru v kódu stačí toto:

Dim nsmgr As XmlNamespaceManager = New XmlNamespaceManager(xmlSourceDocument.NameTable)
        nsmgr.AddNamespace("defaultns", "urn:oasis:names:tc:xliff:document:1.2")
        nsmgr.AddNamespace("sdl", "http://sdl.com/FileTypes/SdlXliff/1.0")

Ten String.Empty tam být nemusí (opět aspoň v mém případě to takto funguje).

Edit: Ještě samotný dotaz na počet elementů, ten mi tedy funguje s touto syntaxí:

fileCount = xmlSourceDocument.SelectNodes("//defaultns:file", nsmgr).Count

Ještě jednou díky za pomoc.

Vladimír Vašek

nahlásit spamnahlásit spam 0 odpovědětodpovědět

1.) Ano, tyto importy platí pouze pro XDocument (XML literály jsou součástí syntaxe jazyka a proto rozlišení namespaců musí být také na úrovni jednotky kódu - proto Imports)

2.) Ano, String.Empty tam být nemusí, protože znamená prázdný namespace, nikoliv výchozí namespace a Váš dokument prázdný namespace nepoužívá. Odstraním to v původním příspěvku.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback