2012-02-17 14 views
13

Wszystko, co robisz w XML, rozróżnia duże i małe litery. Wiem o tym.Analizator składni niewrażliwy na wielkość liter w C#

Jednak obecnie znajduję się w sytuacji, w której oprogramowanie, które piszę, spowodowałoby znacznie mniej błędów, gdybym w jakiś sposób uczynił niewrażliwą wielkość rozpoznawania znaczników xml/atrybutów. Case niewrażliwy na XPath byłby wysłanym bogiem.

Czy istnieje prosty sposób/biblioteka to zrobić w języku C#?

+0

Nie jest prawdopodobne. Ale możesz zrobić 'XElement.Parse (xmlText.Tolower())' –

+0

Dokument XMl może mieć dwa * różne * elementy o nazwach odpowiednio: 'MyName' i' myName' - które mają być różne. Konwersja/traktowanie ich jako tej samej nazwy jest błędem, który może mieć poważne konsekwencje. –

Odpowiedz

14

dokument XML może mieć dwa różne elementy nazwanych odpowiednio: MyName i myName - które mają być różne. Konwersja/traktowanie ich jako tej samej nazwy jest błędem, który może mieć poważne konsekwencje.

W przypadku powyższego nie jest to przypadek, to tutaj jest bardziej precyzyjne rozwiązanie, za pomocą XSLT, aby przetworzyć dokument na taki, który ma tylko małe nazwy elementów i małych nazwy atrybutu:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:variable name="vUpper" select= 
"'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/> 

<xsl:variable name="vLower" select= 
"'abcdefghijklmnopqrstuvwxyz'"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="*[name()=local-name()]" priority="2"> 
    <xsl:element name="{translate(name(), $vUpper, $vLower)}" 
    namespace="{namespace-uri()}"> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:element> 
</xsl:template> 

<xsl:template match="*" priority="1"> 
    <xsl:element name= 
    "{substring-before(name(), ':')}:{translate(local-name(), $vUpper, $vLower)}" 
    namespace="{namespace-uri()}"> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:element> 
</xsl:template> 

<xsl:template match="@*[name()=local-name()]" priority="2"> 
    <xsl:attribute name="{translate(name(), $vUpper, $vLower)}" 
    namespace="{namespace-uri()}"> 
     <xsl:value-of select="."/> 
    </xsl:attribute> 
</xsl:template> 

<xsl:template match="@*" priority="1"> 
    <xsl:attribute name= 
    "{substring-before(name(), ':')}:{translate(local-name(), $vUpper, $vLower)}" 
    namespace="{namespace-uri()}"> 
    <xsl:value-of select="."/> 
    </xsl:attribute> 
</xsl:template> 
</xsl:stylesheet> 

kiedy transformacja ta jest stosowana na dowolnym dokumencie XML, na przykład ten jeden:

<authors xmlns:user="myNamespace"> 
    <?ttt This is a PI ?> 
    <Author xmlns:user2="myNamespace2"> 
    <Name idd="VH">Victor Hugo</Name> 
    <user2:Name idd="VH">Victor Hugo</user2:Name> 
    <Nationality xmlns:user3="myNamespace3">French</Nationality> 
    </Author> 
    <!-- This is a very long comment the purpose is 
     to test the default stylesheet for long comments--> 
    <Author Period="classical"> 
    <Name>Sophocles</Name> 
    <Nationality>Greek</Nationality> 
    </Author> 
    <author> 
    <Name>Leo Tolstoy</Name> 
    <Nationality>Russian</Nationality> 
    </author> 
    <Author> 
    <Name>Alexander Pushkin</Name> 
    <Nationality>Russian</Nationality> 
    </Author> 
    <Author Period="classical"> 
    <Name>Plato</Name> 
    <Nationality>Greek</Nationality> 
    </Author> 
</authors> 

się potrzebne, poprawny wynik (nazwy elementów i atrybutów c onverted na małe litery) jest produkowany:

<authors><?ttt This is a PI ?> 
    <author> 
     <name idd="VH">Victor Hugo</name> 
     <user2:name xmlns:user2="myNamespace2" idd="VH">Victor Hugo</user2:name> 
     <nationality>French</nationality> 
    </author><!-- This is a very long comment the purpose is 
     to test the default stylesheet for long comments--> 
    <author period="classical"> 
     <name>Sophocles</name> 
     <nationality>Greek</nationality> 
    </author> 
    <author> 
     <name>Leo Tolstoy</name> 
     <nationality>Russian</nationality> 
    </author> 
    <author> 
     <name>Alexander Pushkin</name> 
     <nationality>Russian</nationality> 
    </author> 
    <author period="classical"> 
     <name>Plato</name> 
     <nationality>Greek</nationality> 
    </author> 
</authors> 

Gdy dokument jest przetwarzany do pożądanej postaci, a następnie można wykonać dowolną obróbkę na przebudowanej dokumentu.

+0

wygląda całkiem nieźle –

+0

@ArsenZahray: Nie ma za co. –

7

XML to tekst. Wystarczy ToLower go przed załadowaniem do dowolnego parsera, którego używasz.

Dopóki nie trzeba sprawdzać poprawności względem schematu i nie ma nic przeciwko wartościom wszystkich małych liter, to powinno działać dobrze.


Faktem jest, że każdy parser XML będzie być wielkość liter. Gdyby tak nie było, nie byłby parserem XML.

+8

Ale prawdopodobnie nie chcesz "ToLower" swoje wartości – CaffGeek

+1

@Chad - Prawdopodobnie. Złożyłem to zastrzeżenie w mojej odpowiedzi. – Oded

+0

Myślałem o tym. W większości przypadków będzie to działało, z tym że czasami pola mogą zawierać informacje, w których chcę zachować skrzynkę. Na przykład hasła, skróty i inne rzeczy do zewnętrznego świata. Z drugiej strony, tak naprawdę nie muszę rozróżniać atrybutów Nazwa i Nazwa w Xhtml –

11

Można tworzyć case-niewrażliwy metod (rozszerzenia dla użyteczność), np .:

public static class XDocumentExtensions 
{ 
    public static IEnumerable<XElement> ElementsCaseInsensitive(this XContainer source, 
     XName name) 
    { 
     return source.Elements() 
      .Where(e => e.Name.Namespace == name.Namespace 
       && e.Name.LocalName.Equals(name.LocalName, StringComparison.OrdinalIgnoreCase)); 
    } 
} 
0

Zacznę od przekonwertowania wszystkich znaczników i nazw atrybutów na małe litery, pozostawiając wartości nietknięte, za pomocą analizy składniowej SAX, tj. z XmlTextReader.

Powiązane problemy