Анализатор XML без учета регистра в c # - PullRequest
15 голосов
/ 18 февраля 2012

Все, что вы делаете с XML, чувствительно к регистру, я знаю это.

Однако, сейчас я нахожусь в ситуации, когда программное обеспечение, которое я пишу, будет давать гораздо меньше ошибок, если я каким-то образом сделаю xmlраспознавание имени / атрибута без учета регистра.XPath без учета регистра будет отправлено богом.

Есть ли простой способ / библиотека для этого в c #?

Ответы [ 5 ]

14 голосов
/ 18 февраля 2012

Документ XMl может иметь два разных элемента с именами соответственно: MyName и myName - которые должны быть разными. Преобразование / обработка их как одного и того же имени - ошибка, которая может иметь серьезные последствия.

Если вышеприведенное не так, то вот более точное решение, использующее XSLT для обработки документа в тот, который имеет только строчные имена элементов и строчные имена атрибутов:

<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>

когда это преобразование применяется к любому документу XML, например к этому :

<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>

желаемый, правильный результат (имена элементов и атрибутов преобразуются в нижний регистр) :

<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>

Как только документ преобразован в желаемую форму, вы можете выполнить любую необходимую обработку преобразованного документа.

13 голосов
/ 18 февраля 2012

Вы можете создавать нечувствительные к регистру методы (расширения для удобства использования), например ::10000

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));
    }
}
7 голосов
/ 18 февраля 2012

XML это текст. Просто ToLower перед загрузкой в ​​любой используемый вами парсер.

До тех пор, пока вам не нужно проверять по схеме и не возражаете против значений, являющихся строчными, это должно работать просто отлично.


Дело в том, что любой синтаксический анализатор XML будет чувствительным к регистру. Если бы это было не так, это был бы не парсер XML.

0 голосов
/ 01 апреля 2019

Я использую другое решение.Люди хотят этого, потому что вы не хотите дублировать имя свойства в файле класса в атрибуте.Поэтому я добавляю пользовательский атрибут ко всем свойствам:

[AttributeUsage(AttributeTargets.Property)]
public class UsePropertyNameToLowerAsXmlElementAttribute: XmlElementAttribute
{
    public UsePropertyNameToLowerAsXmlElementAttribute([CallerMemberName] string propertyName = null)
    : base(propertyName?.ToLower())
    {
    }
}

Таким образом, сериализатор XML может отображать свойства нижнего регистра в классы CamelCased.декоратор, который говорит, что что-то другое, но у вас нет лишних затрат на маркировку каждого свойства с именем:

public class Settings
{
    [UsePropertyNameToLowerAsXmlElement]
    public string VersionId { get; set; }

    [UsePropertyNameToLowerAsXmlElement]
    public int? ApplicationId { get; set; }
}
0 голосов
/ 10 марта 2012

Я бы начал с преобразования всех тегов и имен атрибутов в нижний регистр, оставив значения нетронутыми, используя синтаксический анализ SAX, т.е.с XmlTextReader.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...