/// <summary> /// Emits a valid XML local-name (i.e. encodes invalid chars including ':') /// </summary> /// <param name="writer"></param> /// <param name="value"></param> /// <remarks> /// Explicitly escaping ':' to maintain compatibility with XML Namespaces. /// From XML 1.0, 5th ed. http://www.w3.org/TR/xml/#sec-common-syn /// Name = NameStartChar (NameChar)* /// NameStartChar = ":" /// | [A-Z] /// | "_" /// | [a-z] /// | [#xC0-#xD6] /// | [#xD8-#xF6] /// | [#xF8-#x2FF] /// | [#x370-#x37D] /// | [#x37F-#x1FFF] /// | [#x200C-#x200D] /// | [#x2070-#x218F] /// | [#x2C00-#x2FEF] /// | [#x3001-#xD7FF] /// | [#xF900-#xFDCF] /// | [#xFDF0-#xFFFD] /// | [#x10000-#xEFFFF] /// NameChar = NameStartChar /// | "-" /// | "." /// | [0-9] /// | #xB7 /// | [#x0300-#x036F] /// | [#x203F-#x2040] /// </remarks> private void WriteLocalName(TextWriter writer, string value) { int start = 0, length = value.Length; for (int i = start; i < length; i++) { char ch = value[i]; if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_') || (ch >= '\u00C0' && ch <= '\u00D6') || (ch >= '\u00D8' && ch <= '\u00F6') || (ch >= '\u00F8' && ch <= '\u02FF') || (ch >= '\u0370' && ch <= '\u037D') || (ch >= '\u037F' && ch <= '\u1FFF') || (ch >= '\u200C' && ch <= '\u200D') || (ch >= '\u2070' && ch <= '\u218F') || (ch >= '\u2C00' && ch <= '\u2FEF') || (ch >= '\u3001' && ch <= '\uD7FF') || (ch >= '\uF900' && ch <= '\uFDCF') || (ch >= '\uFDF0' && ch <= '\uFFFD')) { // purposefully leaving out ':' to implement namespace prefixes // and cannot represent [#x10000-#xEFFFF] as single char so this will incorrectly escape continue; } if ((i > 0) && ((ch >= '0' && ch <= '9') || (ch == '-') || (ch == '.') || (ch == '\u00B7') || (ch >= '\u0300' && ch <= '\u036F') || (ch >= '\u203F' && ch <= '\u2040'))) { // these chars are only valid after initial char continue; } if (i > start) { // copy any leading unescaped chunk writer.Write(value.Substring(start, i - start)); } start = i + 1; // use XmlSerializer-hex-style encoding of UTF-16 writer.Write("_x"); writer.Write(CharUtility.ConvertToUtf32(value, i).ToString("X4")); writer.Write("_"); } if (length > start) { // copy any trailing unescaped chunk writer.Write(value.Substring(start, length - start)); } }
public void CharUtility_SameChar_1() { Assert.IsTrue(CharUtility.SameChar('a', 'a')); Assert.IsTrue(CharUtility.SameChar('a', 'A')); Assert.IsTrue(CharUtility.SameChar('A', 'A')); Assert.IsFalse(CharUtility.SameChar('a', 'B')); }
private static void SkipWhitespace(ITextStream scanner) { while (!scanner.IsCompleted && CharUtility.IsWhiteSpace(scanner.Peek())) { scanner.Pop(); } }
public void CharUtility_OneOf_2() { Assert.IsTrue(CharUtility.OneOf('a', 'a', 'b', 'c')); Assert.IsTrue(CharUtility.OneOf('b', 'a', 'b', 'c')); Assert.IsTrue(CharUtility.OneOf('c', 'a', 'b', 'c')); Assert.IsFalse(CharUtility.OneOf('d', 'a', 'b', 'c')); Assert.IsFalse(CharUtility.OneOf(' ', 'a', 'b', 'c')); }
public void CharUtility_IsUrlSafeChar_1() { Assert.IsTrue(CharUtility.IsUrlSafeChar('A')); Assert.IsTrue(CharUtility.IsUrlSafeChar('Z')); Assert.IsTrue(CharUtility.IsUrlSafeChar('a')); Assert.IsTrue(CharUtility.IsUrlSafeChar('z')); Assert.IsTrue(CharUtility.IsUrlSafeChar('_')); Assert.IsTrue(CharUtility.IsUrlSafeChar('-')); Assert.IsFalse(CharUtility.IsUrlSafeChar('%')); Assert.IsFalse(CharUtility.IsUrlSafeChar('/')); Assert.IsFalse(CharUtility.IsUrlSafeChar('\0')); }
public void CharUtility_OneOf_1() { List <char> list = new List <char> { 'a', 'b', 'c' }; Assert.IsTrue(CharUtility.OneOf('a', list)); Assert.IsTrue(CharUtility.OneOf('b', list)); Assert.IsTrue(CharUtility.OneOf('c', list)); Assert.IsFalse(CharUtility.OneOf('d', list)); Assert.IsFalse(CharUtility.OneOf(' ', list)); }
public override string ToString() { byte[] bytes = this.Bytes; if (bytes == null) { bytes = BsonObjectID.Empty.Bytes; } char[] hex = new char[24]; for (int i = 0, j = 0; i < 24; i += 2, j++) { hex[i] = CharUtility.GetHexDigit(bytes[j] / 0x10); hex[i] = CharUtility.GetHexDigit(bytes[j] % 0x10); } return(new String(hex)); }
/// <summary> /// Scans for the longest valid EcmaScript identifier /// </summary> /// <returns>identifier</returns> /// <remarks> /// http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf /// /// IdentifierName = /// IdentifierStart | IdentifierName IdentifierPart /// IdentifierStart = /// Letter | '$' | '_' /// IdentifierPart = /// IdentifierStart | Digit /// </remarks> private static string ScanIdentifier(ITextStream scanner) { bool identPart = false; scanner.BeginChunk(); while (true) { char ch = scanner.Peek(); // digits are only allowed after first char // rest can be in head or tail if ((identPart && CharUtility.IsDigit(ch)) || CharUtility.IsLetter(ch) || (ch == '_') || (ch == '$')) { identPart = true; scanner.Pop(); ch = scanner.Peek(); continue; } // get ident string return(scanner.EndChunk()); } }
private static void HtmlAttributeEncode(TextWriter writer, string value, bool encodeNonAscii, bool canonicalForm) { if (String.IsNullOrEmpty(value)) { return; } int start = 0, length = value.Length; for (int i = start; i < length; i++) { char ch = value[i]; string entity; switch (ch) { case '<': { entity = "<"; break; } case '>': { if (canonicalForm) { // http://www.w3.org/TR/xml-c14n#ProcessingModel continue; } entity = ">"; break; } case '&': { entity = "&"; break; } case '"': { entity = """; break; } case '\'': { if (!canonicalForm) { continue; } // http://www.w3.org/TR/xml-c14n#ProcessingModel entity = "'"; break; } default: { if ((ch < ' ') || (encodeNonAscii && (ch >= 0x7F)) || ((ch >= 0x7F) && (ch <= 0x84)) || ((ch >= 0x86) && (ch <= 0x9F)) || ((ch >= 0xFDD0) && (ch <= 0xFDEF))) { // encode all control chars: http://www.w3.org/TR/xml/#charsets int utf16 = CharUtility.ConvertToUtf32(value, i); entity = String.Concat("&#x", utf16.ToString("X", CultureInfo.InvariantCulture), ';'); break; } continue; } } if (i > start) { // copy any leading unescaped chunk writer.Write(value.Substring(start, i - start)); } start = i + 1; // use XML named entity writer.Write(entity); } if (length > start) { // copy any trailing unescaped chunk writer.Write(value.Substring(start, length - start)); } }
private static void HtmlEncode(TextWriter writer, string value, bool encodeNonAscii, bool canonicalForm) { int start = 0, length = value.Length; for (int i = start; i < length; i++) { char ch = value[i]; string entity; switch (ch) { case '<': { entity = "<"; break; } case '>': { entity = ">"; break; } case '&': { entity = "&"; break; } case '\r': { if (!canonicalForm) { continue; } // Line breaks normalized to '\n' // http://www.w3.org/TR/xml-c14n#Terminology entity = String.Empty; break; } default: { if (((ch < ' ') && (ch != '\n') && (ch != '\t')) || (encodeNonAscii && (ch >= 0x7F)) || ((ch >= 0x7F) && (ch <= 0x84)) || ((ch >= 0x86) && (ch <= 0x9F)) || ((ch >= 0xFDD0) && (ch <= 0xFDEF))) { // encode all control chars except CRLF/Tab: http://www.w3.org/TR/xml/#charsets int utf16 = CharUtility.ConvertToUtf32(value, i); entity = String.Concat("&#x", utf16.ToString("X", CultureInfo.InvariantCulture), ';'); break; } continue; } } if (i > start) { // copy any leading unescaped chunk writer.Write(value.Substring(start, i - start)); } start = i + 1; // emit XML entity writer.Write(entity); } if (length > start) { // copy any trailing unescaped chunk writer.Write(value.Substring(start, length - start)); } }
/// <summary> /// Consumes a sequence of tokens and produces a token sequence of a different type /// </summary> public IEnumerable <Token <ModelTokenType> > Transform(IEnumerable <Token <MarkupTokenType> > input) { if (input == null) { throw new ArgumentNullException("input"); } IStream <Token <MarkupTokenType> > stream = Stream <Token <MarkupTokenType> > .Create(input); PrefixScopeChain scopeChain = new PrefixScopeChain(); Token <MarkupTokenType> token = stream.Peek(); while (!stream.IsCompleted) { switch (token.TokenType) { case MarkupTokenType.ElementBegin: case MarkupTokenType.ElementVoid: { bool hasProperties = false; bool isVoid = (token.TokenType == MarkupTokenType.ElementVoid); DataName tagName = token.Name; yield return(ModelGrammar.TokenArrayBeginUnnamed); // NOTE: JSON doesn't support namespaces so resolve the name to prefix+':'+local-name yield return(ModelGrammar.TokenPrimitive(tagName.ToPrefixedName())); PrefixScopeChain.Scope scope = new PrefixScopeChain.Scope(); string prefix = scopeChain.GetPrefix(tagName.NamespaceUri, false); if (!StringComparer.Ordinal.Equals(prefix, tagName.Prefix) && !String.IsNullOrEmpty(tagName.NamespaceUri)) { scope[tagName.Prefix] = tagName.NamespaceUri; // new namespace scope so need to emit xmlns hasProperties = true; yield return(ModelGrammar.TokenObjectBeginUnnamed); } scope.TagName = tagName; scopeChain.Push(scope); stream.Pop(); token = stream.Peek(); while (!stream.IsCompleted && token.TokenType == MarkupTokenType.Attribute) { if (!hasProperties) { hasProperties = true; yield return(ModelGrammar.TokenObjectBeginUnnamed); } DataName attrName = token.Name; prefix = scopeChain.GetPrefix(attrName.NamespaceUri, false); if (!StringComparer.Ordinal.Equals(prefix, attrName.Prefix) && !String.IsNullOrEmpty(attrName.NamespaceUri)) { scope[attrName.Prefix] = attrName.NamespaceUri; } // NOTE: JSON doesn't support namespaces so resolve the name to prefix+':'+local-name yield return(ModelGrammar.TokenProperty(new DataName(attrName.ToPrefixedName()))); stream.Pop(); token = stream.Peek(); switch (token.TokenType) { case MarkupTokenType.Primitive: { yield return(token.ChangeType(ModelTokenType.Primitive)); break; } default: { throw new TokenException <MarkupTokenType>( token, String.Format(ErrorUnexpectedToken, token.TokenType)); } } stream.Pop(); token = stream.Peek(); } if (hasProperties) { foreach (var xmlns in scope) { if (String.IsNullOrEmpty(xmlns.Key)) { yield return(ModelGrammar.TokenProperty("xmlns")); } else { yield return(ModelGrammar.TokenProperty(String.Concat("xmlns:", xmlns.Key))); } yield return(ModelGrammar.TokenPrimitive(xmlns.Value)); } yield return(ModelGrammar.TokenObjectEnd); } if (isVoid) { yield return(ModelGrammar.TokenArrayEnd); scopeChain.Pop(); } break; } case MarkupTokenType.ElementEnd: { if (scopeChain.Count > 0) { yield return(ModelGrammar.TokenArrayEnd); } scopeChain.Pop(); stream.Pop(); token = stream.Peek(); break; } case MarkupTokenType.Primitive: { if (token.Value is ITextFormattable <ModelTokenType> || token.Value is ITextFormattable <MarkupTokenType> ) { yield return(token.ChangeType(ModelTokenType.Primitive)); stream.Pop(); token = stream.Peek(); break; } string value = token.ValueAsString(); stream.Pop(); token = stream.Peek(); while (!stream.IsCompleted && (token.TokenType == MarkupTokenType.Primitive) && !(token.Value is ITextFormattable <ModelTokenType>) && !(token.Value is ITextFormattable <MarkupTokenType>)) { // concatenate adjacent value nodes value = String.Concat(value, token.ValueAsString()); stream.Pop(); token = stream.Peek(); } switch (this.Whitespace) { case WhitespaceType.Normalize: { // replace whitespace chunks with single space (HTML-style normalization) value = JsonMLInTransformer.RegexWhitespace.Replace(value, JsonMLInTransformer.SingleSpace); goto default; } case WhitespaceType.None: { if (CharUtility.IsNullOrWhiteSpace(value)) { break; } goto default; } case WhitespaceType.Preserve: default: { yield return(ModelGrammar.TokenPrimitive(value)); break; } } break; } case MarkupTokenType.Attribute: default: { throw new TokenException <MarkupTokenType>( token, String.Format(ErrorUnexpectedToken, token.TokenType)); } } } while (scopeChain.Count > 0) { scopeChain.Pop(); yield return(ModelGrammar.TokenArrayEnd); } }
private static string ScanString(ITextStream scanner) { // store for unterminated cases long strPos = scanner.Index + 1; int strLine = scanner.Line; int strCol = scanner.Column; char stringDelim = scanner.Peek(); scanner.Pop(); char ch = scanner.Peek(); // start chunking scanner.BeginChunk(); StringBuilder buffer = new StringBuilder(JsonTokenizer.DefaultBufferSize); while (true) { // look ahead if (scanner.IsCompleted || CharUtility.IsControl(ch) && ch != '\t') { // reached end or line break before string delim throw new DeserializationException(JsonTokenizer.ErrorUnterminatedString, strPos, strLine, strCol); } // check each character for ending delim if (ch == stringDelim) { // end chunking scanner.EndChunk(buffer); // flush closing delim scanner.Pop(); // output string return(buffer.ToString()); } if (ch != JsonGrammar.OperatorCharEscape) { // accumulate scanner.Pop(); ch = scanner.Peek(); continue; } // pause chunking to replace escape char scanner.EndChunk(buffer); // flush escape char scanner.Pop(); ch = scanner.Peek(); if (scanner.IsCompleted || CharUtility.IsControl(ch) && ch != '\t') { // reached end or line break before string delim throw new DeserializationException(JsonTokenizer.ErrorUnterminatedString, strPos, strLine, strCol); } // begin decode switch (ch) { case '0': { // consume and do not allow NULL char '\0' // causes CStrings to terminate scanner.Pop(); ch = scanner.Peek(); break; } case 'b': { // backspace buffer.Append('\b'); scanner.Pop(); ch = scanner.Peek(); break; } case 'f': { // formfeed buffer.Append('\f'); scanner.Pop(); ch = scanner.Peek(); break; } case 'n': { // newline buffer.Append('\n'); scanner.Pop(); ch = scanner.Peek(); break; } case 'r': { // carriage return buffer.Append('\r'); scanner.Pop(); ch = scanner.Peek(); break; } case 't': { // tab buffer.Append('\t'); scanner.Pop(); ch = scanner.Peek(); break; } case 'u': { // Unicode escape sequence // e.g. (c) => "\u00A9" const int UnicodeEscapeLength = 4; scanner.Pop(); ch = scanner.Peek(); string escapeSeq = String.Empty; for (int i = UnicodeEscapeLength; !scanner.IsCompleted && CharUtility.IsHexDigit(ch) && (i > 0); i--) { escapeSeq += ch; scanner.Pop(); ch = scanner.Peek(); } // unicode ordinal int utf16 = 0; bool parsed = true; try{ utf16 = Int32.Parse( escapeSeq, NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo); }catch (Exception) { parsed = false; }; if (escapeSeq.Length == UnicodeEscapeLength && parsed) { buffer.Append(CharUtility.ConvertFromUtf32(utf16)); } else { // using FireFox-style recovery, if not a valid hex // escape sequence then treat as single escaped 'u' // followed by rest of string buffer.Append('u'); buffer.Append(escapeSeq); } break; } default: { // all unrecognized sequences are interpreted as plain chars buffer.Append(ch); scanner.Pop(); ch = scanner.Peek(); break; } } // resume chunking scanner.BeginChunk(); } }
private static Token <ModelTokenType> ScanNumber(ITextStream scanner) { // store for error cases long numPos = scanner.Index + 1; int numLine = scanner.Line; int numCol = scanner.Column; scanner.BeginChunk(); char ch = scanner.Peek(); bool isNeg = false; if (ch == JsonGrammar.OperatorUnaryPlus) { // consume positive signing (as is extraneous) scanner.Pop(); ch = scanner.Peek(); // reset buffering scanner.BeginChunk(); } else if (ch == JsonGrammar.OperatorUnaryMinus) { // optional minus part scanner.Pop(); ch = scanner.Peek(); isNeg = true; } if (!CharUtility.IsDigit(ch) && ch != JsonGrammar.OperatorDecimalPoint) { // possibly "-Infinity" scanner.EndChunk(); return(null); } // integer part while (!scanner.IsCompleted && CharUtility.IsDigit(ch)) { // consume digit scanner.Pop(); ch = scanner.Peek(); } bool hasDecimal = false; if (!scanner.IsCompleted && (ch == JsonGrammar.OperatorDecimalPoint)) { // consume decimal scanner.Pop(); ch = scanner.Peek(); // fraction part while (!scanner.IsCompleted && CharUtility.IsDigit(ch)) { // consume digit scanner.Pop(); ch = scanner.Peek(); hasDecimal = true; } if (!hasDecimal) { // fractional digits required when '.' present throw new DeserializationException(JsonTokenizer.ErrorIllegalNumber, numPos, numLine, numCol); } } // note the number of significant digits int precision = scanner.ChunkSize; if (hasDecimal) { precision--; } if (isNeg) { precision--; } if (precision < 1) { // missing digits all together throw new DeserializationException(JsonTokenizer.ErrorIllegalNumber, numPos, numLine, numCol); } bool hasExponent = false; // optional exponent part if (!scanner.IsCompleted && (ch == 'e' || ch == 'E')) { // consume 'e' scanner.Pop(); ch = scanner.Peek(); // optional minus/plus part if (!scanner.IsCompleted && ch == JsonGrammar.OperatorUnaryMinus || ch == JsonGrammar.OperatorUnaryPlus) { // consume sign scanner.Pop(); ch = scanner.Peek(); } // exp part while (!scanner.IsCompleted && CharUtility.IsDigit(ch)) { // consume digit scanner.Pop(); ch = scanner.Peek(); hasExponent = true; } if (!hasExponent) { // exponent digits required when 'e' present throw new DeserializationException(JsonTokenizer.ErrorIllegalNumber, numPos, numLine, numCol); } } // specifically check for 0x-style hex numbers if (!scanner.IsCompleted && CharUtility.IsLetter(ch)) { throw new DeserializationException(JsonTokenizer.ErrorIllegalNumber, numPos, numLine, numCol); } // by this point, we have the full number string and know its characteristics string buffer = scanner.EndChunk(); if (!hasDecimal && !hasExponent && precision < 19) { // Integer value decimal number = 0; try{ number = Decimal.Parse( buffer, NumberStyles.Integer, NumberFormatInfo.InvariantInfo); }catch (Exception) { throw new DeserializationException(JsonTokenizer.ErrorIllegalNumber, numPos, numLine, numCol); } if (number >= Int32.MinValue && number <= Int32.MaxValue) { // int most common return(ModelGrammar.TokenPrimitive((int)number)); } if (number >= Int64.MinValue && number <= Int64.MaxValue) { // long more flexible return(ModelGrammar.TokenPrimitive((long)number)); } // decimal most flexible return(ModelGrammar.TokenPrimitive(number)); } else { // Floating Point value double number; try{ number = Double.Parse( buffer, NumberStyles.Float, NumberFormatInfo.InvariantInfo); }catch (Exception) { throw new DeserializationException(JsonTokenizer.ErrorIllegalNumber, numPos, numLine, numCol); } // native EcmaScript number (IEEE-754) return(ModelGrammar.TokenPrimitive(number)); } }
protected virtual void WriteString(TextWriter writer, string value) { int start = 0, length = value.Length; writer.Write(JsonGrammar.OperatorStringDelim); for (int i = start; i < length; i++) { char ch = value[i]; if (ch <= '\u001F' || ch >= '\u007F' || (this.encodeLessThan && ch == '<') || // improves compatibility within script blocks ch == JsonGrammar.OperatorStringDelim || ch == JsonGrammar.OperatorCharEscape) { if (i > start) { writer.Write(value.Substring(start, i - start)); } start = i + 1; switch (ch) { case JsonGrammar.OperatorStringDelim: case JsonGrammar.OperatorCharEscape: { writer.Write(JsonGrammar.OperatorCharEscape); writer.Write(ch); continue; } case '\b': { writer.Write("\\b"); continue; } case '\f': { writer.Write("\\f"); continue; } case '\n': { writer.Write("\\n"); continue; } case '\r': { writer.Write("\\r"); continue; } case '\t': { writer.Write("\\t"); continue; } default: { writer.Write("\\u"); writer.Write(CharUtility.ConvertToUtf32(value, i).ToString("X4")); continue; } } } } if (length > start) { writer.Write(value.Substring(start, length - start)); } writer.Write(JsonGrammar.OperatorStringDelim); }
private IList <Token <ModelTokenType> > TransformElement(IStream <Token <MarkupTokenType> > input, bool isStandAlone) { Token <MarkupTokenType> token = input.Peek(); DataName elementName = this.DecodeName(token.Name, typeof(Object)); bool isVoid = (token.TokenType == MarkupTokenType.ElementVoid); input.Pop(); IDictionary <DataName, IList <IList <Token <ModelTokenType> > > > children = null; while (!input.IsCompleted) { token = input.Peek(); if (token.TokenType == MarkupTokenType.ElementEnd || (isVoid && token.TokenType != MarkupTokenType.Attribute)) { if (!isVoid) { input.Pop(); } List <Token <ModelTokenType> > output = new List <Token <ModelTokenType> >(); if ((children == null) || (children.Count <= 1) || elementName == XmlInTransformer.DefaultArrayName) { DataName childName = DataName.Empty; IList <IList <Token <ModelTokenType> > > items = null; if (children != null) { // grab the first using (var enumerator = children.GetEnumerator()) { if (enumerator.MoveNext()) { items = enumerator.Current.Value; childName = enumerator.Current.Key; } } } if ((items != null && items.Count > 1) || (items == null && elementName == XmlInTransformer.DefaultArrayName) || childName == XmlInTransformer.DefaultItemName) { // if only child has more than one grandchild // then whole element is acutally an array output.Add(elementName.IsEmpty ? ModelGrammar.TokenArrayBeginUnnamed : ModelGrammar.TokenArrayBegin(this.DecodeName(elementName, typeof(Array)))); if (items != null) { foreach (var item in items) { output.AddRange(item); } } output.Add(ModelGrammar.TokenArrayEnd); return(output); } } if (isStandAlone) { output.Add(elementName.IsEmpty ? ModelGrammar.TokenObjectBeginUnnamed : ModelGrammar.TokenObjectBegin(elementName)); } if (children != null) { foreach (var property in children) { if (property.Value.Count == 1) { if (isStandAlone) { // if the parent is a stand alone object then child is a property DataName name = this.DecodeName(property.Key, typeof(Object)); output.Add(name.IsEmpty ? ModelGrammar.TokenProperty(elementName) : ModelGrammar.TokenProperty(name)); } output.AddRange(property.Value[0]); continue; } if (property.Key.IsEmpty) { // skip mixed content continue; } // wrap values in array output.Add(property.Key.IsEmpty ? ModelGrammar.TokenArrayBeginUnnamed : ModelGrammar.TokenArrayBegin(this.DecodeName(property.Key, typeof(Array)))); foreach (var item in property.Value) { output.AddRange(item); } output.Add(ModelGrammar.TokenArrayEnd); } } else if (!isStandAlone) { output.Add(ModelGrammar.TokenNull); } if (isStandAlone) { output.Add(ModelGrammar.TokenObjectEnd); } return(output); } DataName propertyName = token.Name; if (token.TokenType == MarkupTokenType.Attribute) { input.Pop(); } if (children == null) { children = new Dictionary <DataName, IList <IList <Token <ModelTokenType> > > >(); } if (!children.ContainsKey(propertyName)) { children[propertyName] = new List <IList <Token <ModelTokenType> > >(); } var child = this.TransformValue(input, !isStandAlone); if (child.Count == 1 && child[0].TokenType == ModelTokenType.Primitive && child[0].Value != null && CharUtility.IsNullOrWhiteSpace(child[0].ValueAsString())) { // skip whitespace mixed content continue; } children[propertyName].Add(child); } throw new TokenException <MarkupTokenType>( token, XmlInTransformer.ErrorUnterminatedObject); }
static void Main(string[] args) { if (args.Length != 3) { Console.WriteLine ( "RecordDumper <connection-string> " + "<search-expression> <output-file>" ); return; } string connectionString = args[0]; string searchExpression = args[1]; string outputFileName = args[2]; try { JObject config = JsonUtility.ReadObjectFromFile("dumperConfig.json"); int etalonTag = config["etalonTag"].Value <int>(); int[] excludeTags = config["excludeTags"] .Values <int>().ToArray(); string[] excludePages = config["excludePages"] .Values <string>().ToArray(); using (IrbisProvider provider = ProviderManager .GetAndConfigureProvider(connectionString)) using (StreamWriter writer = TextWriterUtility.Create ( outputFileName, IrbisEncoding.Utf8 )) { FileSpecification specification = new FileSpecification ( IrbisPath.MasterFile, provider.Database, "WS31.OPT" ); IrbisOpt opt = IrbisOpt.LoadFromServer ( provider, specification ); if (ReferenceEquals(opt, null)) { throw new IrbisException("Can't load OPT file!"); } int[] found = provider.Search(searchExpression); Console.WriteLine("Found: {0}", found.Length); foreach (int mfn in found) { MarcRecord record = provider.ReadRecord(mfn); if (ReferenceEquals(record, null)) { continue; } string title = record.FM(etalonTag); if (string.IsNullOrEmpty(title)) { continue; } string wsName = opt.SelectWorksheet(opt.GetWorksheet(record)); if (string.IsNullOrEmpty(wsName)) { continue; } specification = new FileSpecification ( IrbisPath.MasterFile, provider.Database, wsName + ".ws" ); WsFile worksheet = WsFile.ReadFromServer ( provider, specification ); if (ReferenceEquals(worksheet, null)) { continue; } Console.WriteLine("MFN={0}: {1}", mfn, title); writer.WriteLine("<h3>{0}</h3>", title); string description = provider.FormatRecord(record, "@"); writer.WriteLine(description); RecordField[] fields = record.Fields .Where(field => !field.Tag.OneOf(excludeTags)) .ToArray(); writer.WriteLine ( "<table border=\"1\" " + "cellpadding=\"3\" " + "cellspacing=\"0\" " + ">" ); writer.WriteLine ( "<tr bgcolor=\"black\">" + "<th style=\"color:white;text-align:left;\">Поле</th>" + "<th style=\"color:white;text-align:left;\">Подполе</th>" + "<th style=\"color:white;text-align:left;\">Значение</th>" + "</tr>" ); foreach (WorksheetPage page in worksheet.Pages) { if (page.Name.OneOf(excludePages)) { continue; } int[] tags = page.Items .Select(item => item.Tag) .Select(NumericUtility.ParseInt32) .ToArray(); if (!fields.Any(field => field.Tag.OneOf(tags))) { continue; } writer.WriteLine ( "<tr><td colspan=\"3\"><b>Вкладка «{0}»</b></td></tr>", page.Name ); foreach (WorksheetItem item in page.Items) { if (string.IsNullOrEmpty(item.Tag)) { continue; } int tag = NumericUtility.ParseInt32(item.Tag); if (tag <= 0) { continue; } RecordField[] itemFields = fields.GetField(tag); for (int i = 0; i < itemFields.Length; i++) { RecordField field = itemFields[i]; title = item.Title; title = StringUtility.Sparse(title); if (i != 0) { title = string.Format ( "(повторение {0})", i + 1 ); } int rowspan = 1; if (string.IsNullOrEmpty(field.Value)) { rowspan = 1 + field.SubFields.Count; } writer.WriteLine ( "<tr><td rowspan=\"{0}\" \"width=\"{1}\"><b>{2}</b></td><td colspan=\"2\"><b>{3}</b></td></tr>", rowspan, FirstWidth, field.Tag, HtmlText.Encode(title) ); if (!string.IsNullOrEmpty(field.Value)) { writer.WriteLine ( "<tr><td colspan=\"2\"> </td><td>{0}</td></tr>", HtmlText.Encode(field.Value) ); } if (item.EditMode == "5") { string inputInfo = item.InputInfo .ThrowIfNull("item.InputInfo"); // Поле с подполями specification = new FileSpecification ( IrbisPath.MasterFile, provider.Database, inputInfo ); WssFile wss = WssFile.ReadFromServer ( provider, specification ); if (ReferenceEquals(wss, null)) { Console.WriteLine ( "Can't load: " + inputInfo ); } else { foreach (WorksheetItem line in wss.Items) { char code = line.Tag.FirstChar(); SubField subField = field.GetFirstSubField(code); if (!ReferenceEquals(subField, null)) { writer.WriteLine ( "<tr>" + "<td width=\"{0}\"><b>{1}</b>: {2}</td>" + "<td width=\"{3}\">{4}</td></tr>", SecondWidth, CharUtility.ToUpperInvariant(code), HtmlText.Encode(line.Title), ThirdWidth, HtmlText.Encode(subField.Value) ); } } } } } } } writer.WriteLine("</table>"); } } } catch (Exception exception) { Console.WriteLine(exception); } }