Как эффективно проанализировать связанные XML-документы из файла

Не нет. Это используется для преобразования значения в булевскую переменную:

!!nil   #=> false
!!"abc" #=> true
!!false #=> false

обычно не необходимо использовать, хотя, так как единственные ложные значения к Ruby nil и false, таким образом, обычно лучше позволить той конвенции стоять.

Думают о нем как [1 111]

!(!some_val)

Одна вещь, которая является используемым для, законно препятствует тому, чтобы был возвращен огромный блок данных. Например, Вы, вероятно, не хотите возвращать 3 МБ данных изображения в Вашем has_image? метод, или Вы не можете хотеть возвращать свой весь пользовательский объект в logged_in? метод. Используя !! преобразовывает эти объекты в простое true / false.

9
задан Juha Syrjälä 24 August 2009 в 01:46
поделиться

4 ответа

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

В противном случае ищите конечный тег уровня документа. То есть просканируйте текст, считая, на сколько уровней вы находитесь. Каждый раз, когда вы видите тег, который начинается с «<», но не «», добавьте 1 к счетчику глубины. Каждый раз, когда вы видите тэг, начинающийся с «

3
ответ дан 3 November 2019 в 01:02
поделиться

Не разделяйте! Добавьте вокруг него одну большую метку! Затем он снова становится одним файлом XML:

<BIGTAG>
<?xml version="1.0" encoding="UTF-8"?>
<someData>...</someData>
<?xml version="1.0" encoding="UTF-8"?>
<someData>...</someData>
<?xml version="1.0" encoding="UTF-8"?>
<someData>...</someData>
</BIGTAG>

Теперь использование / BIGTAG / SomeData предоставит вам все корни XML.


Если инструкции обработки мешают, вы всегда можете использовать RegEx для их удаления. Легче просто удалить все инструкции обработки, чем использовать регулярное выражение для поиска всех корневых узлов. Если кодировка различается для всех документов, запомните следующее: весь документ должен быть закодирован с помощью некоторого типа кодирования, поэтому все включенные в него XML-документы будут использовать одну и ту же кодировку, независимо от того, что вам сообщает каждый заголовок. Если большой файл закодирован как UTF-16, тогда не имеет значения, говорят ли инструкции обработки XML, что сам XML является UTF-8. Это не будет UTF-8, поскольку весь файл - UTF-16. Кодировка в этих инструкциях обработки XML поэтому недействительна.

Объединив их в один файл, вы изменили кодировку ...


Под RegEx я подразумеваю регулярные выражения. Вам просто нужно удалить весь текст между , который не должен быть слишком сложным с регулярным выражением и немного сложнее, если вы пытаетесь использовать другие методы манипуляции строками.
4
ответ дан 3 November 2019 в 01:02
поделиться

Поскольку вы не уверены, что объявление всегда будет присутствовать, вы можете удалить все объявления (такое регулярное выражение, как <\? Xml version. * \?> может найти их), добавить , добавить , чтобы результирующая строка была допустимым XML-документом. В нем вы можете получить отдельные документы, используя (например) запрос XPath / doc-collection / * . Если объединенный файл может быть достаточно большим, чтобы потребление памяти стало проблемой, вам может потребоваться использовать потоковый синтаксический анализатор, такой как Sax, но принцип остается тем же.

В аналогичном сценарии, с которым я столкнулся, я просто читал объединенные документ напрямую с помощью синтаксического анализатора xml: хотя объединенный файл может не быть действительным xml документом , это действительный xml фрагмент (за исключением повторяющихся объявлений) - так что после удаления объявлений, если ваш синтаксический анализатор поддерживает синтаксический анализ фрагментов, вы также можете просто прочитать результат напрямую. Тогда все элементы верхнего уровня будут корневыми элементами объединенных документов.

Короче говоря, если вы удалите все объявления, у вас будет действительный xml-фрагмент, который можно тривиально проанализировать либо напрямую, либо окружив его некоторым тегом.

3
ответ дан 3 November 2019 в 01:02
поделиться

У меня нет ответа на Java, но вот как я решил эту проблему с помощью C #.

Я создал класс с именем XmlFileStreams для сканирования исходного документа на предмет объявления XML-документа и логического разделения его на несколько документов:

class XmlFileStreams {

    List<int> positions = new List<int>();
    byte[] bytes;

    public XmlFileStreams(string filename) {
        bytes = File.ReadAllBytes(filename);
        for (int pos = 0; pos < bytes.Length - 5; ++pos)
            if (bytes[pos] == '<' && bytes[pos + 1] == '?' && bytes[pos + 2] == 'x' && bytes[pos + 3] == 'm' && bytes[pos + 4] == 'l')
                positions.Add(pos);
        positions.Add(bytes.Length);
    }

    public IEnumerable<Stream> Streams {
        get {
            if (positions.Count > 1)
                for (int i = 0; i < positions.Count - 1; ++i)
                    yield return new MemoryStream(bytes, positions[i], positions[i + 1] - positions[i]);
        }
    }

}

Чтобы использовать XmlFileStreams:

foreach (Stream stream in new XmlFileStreams(@"c:\tmp\test.xml").Streams) {
    using (var xr = XmlReader.Create(stream, new XmlReaderSettings() { XmlResolver = null, ProhibitDtd = false })) {
        // parse file using xr
    }
}

Есть несколько предостережений.

  1. Он считывает весь файл в память для обработки. Это может быть проблемой, если файл действительно большой.
  2. Он использует простой перебор для поиска границ документа XML.
0
ответ дан 3 November 2019 в 01:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: