Как удалить строки из файла xml
В этом разделе показано, как использовать классы пакета Open XML SDK 2.5 для Office для удаления части документа (файла) из текстового документа программными средствами.
Для компиляции кода, представленного в этом разделе, требуются следующие директивы сборки.
Пакеты и части документа
Документ Open XML хранится в виде пакета, формат которого определяется спецификацией ISO/IEC 29500-2. Пакет может состоять из нескольких частей со связями между ними. Связь между частями определяет категорию документа. Документ может быть определен как текстовый документ, если его элемент связи пакета содержит связь с основной частью документа. Если соответствующий элемент содержит связь с частью презентации, он может быть определен как презентация. Если соответствующий элемент содержит связь с частью книги, он определяется как электронная таблица. В этот разделе вы будете использовать пакет текстового документа.
Получение объекта WordprocessingDocument
Пример кода начинается с открытия файла пакета с передачей имени файла в качестве аргумента в один из перегруженных методов Open() DocumentFormat.OpenXml.Packaging.WordprocessingDocument, который принимает строку и логическое значение, которое указывает, следует ли открыть файл в режиме чтения и записи. В этом случае значение логической переменной равно true, что указывает, что файл должен быть открыт в режиме чтения/записи.
Рекомендуется использовать оператор using вместо традиционной последовательности .Create, .Save и .Close. Это позволяет обеспечить автоматический вызов метода Dispose (внутреннего метода, используемого пакетом SDK Open XML для очистки ресурсов) при достижении закрывающей скобки. Блок, следующий за инструкцией using, создает область для объекта, создаваемого или именуемого в оператореusing, в данном случае — wordDoc. Так как класс WordprocessingDocument в пакете SDK Open XML автоматически сохраняет и закрывает объект как часть реализации System.IDisposable, а также поскольку метод Dispose вызывается автоматически при выходе из блока, не нужно явно вызывать методы Save и Close, если используется оператор using.
Базовая структура документа WordProcessingML
Базовая структура документа WordProcessingML состоит из элементов document и body. За ними следуют один или более элементов уровня блока, таких как p, который представляет абзац. Абзац содержит один или несколько элементов r. r означает запуск, являющийся областью текста с общим набором свойств, таких как форматирование. Запуск состоит из одного или нескольких элементов t. Элемент t содержит текст. Разметка WordprocessingML для созданного документа показана в следующем примере кода.
С помощью пакета SDK 2.5 Open XML можно создать структуру и содержимое документа, использующие строго типизированные классы, которые соответствуют элементам WordprocessingML. Эти классы можно найти в пространстве имен DocumentFormat.OpenXml.Wordprocessing. В приведенной ниже таблице представлены имена классов, соответствующие элементам document, body, p, r и t.
Элемент WordprocessingML | Класс пакета Open XML SDK 2.5 | Описание |
---|---|---|
document | Document | Корневой элемент основной части документа. |
body | Body | Контейнер для структур уровня блока, таких как абзацы, аннотации, и других, указанных в спецификации ISO/IEC 29500. |
p | Абзац | Абзац. |
r | Запустить | Запуск. |
t | Текст | Диапазон текста. |
Элемент Settings
Этот элемент определяет параметры, которые применяются в документ WordprocessingML. Этот элемент является корневым элементом части параметров документа в документе WordprocessingML.
Пример: Рассмотрим следующий фрагмент документа WordprocessingML для части параметров документа:
Элементsettings содержит все параметры для данного документа. В этом случае два примененных параметра являются автоматическими позициями табуляции, увеличенной до 0,5" с помощью элемента defaultTabStop и без сжатия уровня символа пробела с помощью элемента characterSpacingControl.
© ISO/IEC29500: 2008.
Как работает пример кода
После открытия документа в инструкции using в качестве объекта WordprocessingDocument создается ссылка на часть DocumentSettingsPart. Можно проверить, существует ли эта часть, и, если она существует, можно удалить ее из пакета. В данном случае из пакета удаляется часть settings.xml.
Пример кода
Следующий код удаляет часть документа из пакета. Для запуска программы вызовите метод RemovePart, как показано в этом примере.
Перед запуском программы на тестового файла "MyPkg6.docs,", например, откройте файл с помощью Open XML SDK 2.5 Productivity Tool для Microsoft Office и проверьте его структуру. После выполнения программы проверьте файл, и вы заметите, что часть DocumentSettingsPart была удалена.
Класс XPathNavigator располагает набором методов, используемых для удаления узлов и значений из XML-документа. Для использования этих методов необходимо сделать редактируемым объект XPathNavigator, то есть установить для свойства CanEdit значение true .
Объекты XPathNavigator для правки XML-документа создаются с помощью метода CreateNavigator класса XmlDocument. Объекты XPathNavigator, созданные классом XPathDocument, доступны только для чтения, и любая попытка вызова методов редактирования объекта XPathNavigator, созданного объектом XPathDocument, приводит к возникновению исключения NotSupportedException.
Дополнительные сведения о доступных только для чтения и изменяемых объектах XPathNavigator см. в руководстве по чтению данных XML с помощью XPathDocument и XmlDocument.
Удаление узлов
Класс XPathNavigator представляет метод DeleteSelf для удаления узлов из XML-документа.
Удаление узла
Класс XPathNavigator представляет метод DeleteSelf для удаления узлов текущего узла, на котором в данное время позиционирован объект XPathNavigator, из XML-документа.
Узел, удаленный с помощью метода DeleteSelf, более недоступен из корня объекта XmlDocument. После удаления узла объект XPathNavigator позиционируется на родительском узле удаленного узла.
Операция удаления не влияет на позицию любого объекта XPathNavigator, позиционированного на удаленном узле. Эти объекты XPathNavigator допустимы в том отношении, что могут перемещаться внутри удаленного поддерева, но не могут быть перенесены в главный узел дерева с помощью обычных методов перемещения по набору узлов класса XPathNavigator.
Метод MoveTo класса XPathNavigator может быть использован для перемещения этих объектов XPathNavigator назад в главный узел дерева или из главного узла дерева в удаленное поддерево.
В следующем примере элемент price первого элемента book файла contosoBooks.xml удаляется с помощью метода DeleteSelf. Позиция объекта XPathNavigator после удаления элемента price - на родительском элементе book .
В примере в качестве входных данных используется файл contosoBooks.xml .
Удаление узла атрибута
Узлы атрибута удаляются из XML-документа с помощью метода DeleteSelf.
Удаленный узел атрибута более недоступен из корневого узла объекта XmlDocument, и объект XPathNavigator позиционируется на родительском элементе.
Атрибуты по умолчанию
Независимо от метода удаления атрибутов, существуют специальные ограничения на удаление атрибутов, определенных как атрибуты по умолчанию в определении DTD или схеме XML для XML-документа. Атрибуты по умолчанию нельзя удалить, если не удален элемент, к которому они принадлежат. Атрибуты по умолчанию всегда присутствуют для элементов с объявленными атрибутами по умолчанию, и в результате удаление атрибута по умолчанию приводит к вставке в элемент атрибута замены, инициируемого с декларированным значением по умолчанию.
Удаление значений
Класс XPathNavigator представляет методы SetValue и SetTypedValue для удаления узлов нетипизированных и типизированных значений из XML-документа.
Удаление нетипизированных значений
Метод SetValue просто вставляет нетипизированное значение string , переданное в качестве параметра, как значение узла, на котором в данный момент позиционируется объект XPathNavigator. Передача пустой строки в метод SetValue удаляет значение текущего узла.
В следующем примере значение элемента price первого элемента book в файле contosoBooks.xml удаляется с помощью метода SetValue.
В примере в качестве входных данных используется файл contosoBooks.xml .
Удаление типизированных значений
Когда тип узла является простым типом XML-схемы W3C, новое значение, вставленное методом SetTypedValue, проверяется по особенностям простого типа, прежде чем будет установлено значение. Если новое значение недопустимо в соответствии с типом узла (например, при установке значения -1 для элемента с типом xs:positiveInteger ), возникает исключение. Методу SetTypedValue также невозможно передать значение null в качестве параметра. В результате удаления значение типизированного узла должно соответствовать типу схемы узла.
В следующем примере значение элемента price первого элемента book в файле contosoBooks.xml удаляется с помощью метода SetTypedValue путем присвоения значения 0 . Значение узла не удаляется, но цена книги удалена в соответствии с ее типом данных xs:decimal .
Узлы пространства имен
Узлы пространства имен нельзя удалить из объекта XmlDocument. Попытки удалить узлы пространства имен с помощью метода DeleteSelf приводят к исключению.
Свойства InnerXml и OuterXml
Свойства InnerXml и OuterXml класса XPathNavigator изменяют XML-разметку узлов, на которых в данный момент позиционируется объект XPathNavigator.
Свойство InnerXml изменяет XML-разметку дочерних узлов, на которых в данный момент позиционируется объект XPathNavigator, разобранный содержимым заданной XML-строки ( string ). Подобным образом свойство OuterXml изменяет XML-разметку дочерних узлов, на которых в данный момент позиционируется объект XPathNavigator, так же как и самого текущего узла.
Сохранение XML-документа
Сохранение изменений, внесенных в объект XmlDocument в результате выполнения описанных в данном разделе методов, выполняется с помощью методов класса XmlDocument. Дополнительные сведения о сохранении изменений, внесенных в объект XmlDocument, см. в руководстве по созданию и сохранению документов.
Как я могу получить следующее с любым существующим инструментом или XSLT?
Я хочу сделать это преобразование, потому что я хочу быстро удалить некоторые записи (в данном случае 'cd') из XML-файла. Использование однострочного формата помогло бы мне.
Я хочу сделать это преобразование, потому что я хочу быстро удалить некоторые записи (в данном случае 'cd') из XML-файла. Использование однострочного формата помогло бы мне.
Извините, но это неправильный подход. Вы хотите использовать XSLT для манипулирования пробелами в вашем документе, чтобы упростить удаление ошибочных строк. чем-то, что не является XSLT? Просто удалите ненужные строки с помощью XSLT!
Базовый пример (непроверенный, но на 99% уверен, что это сработает для данного требования)
Странное требование (не семантика различий). Эта таблица стилей:
Примечание. Правило идентификации, xsl:strip-space (обрезает все текстовые узлы), добавляет новую строку и вкладку для cd и новая строка для последнего cd ,
Ключ должен гарантировать, что выходные данные не имеют автоматического отступа, а затем указать, какие элементы должны удалить пробелы, такие как cd , title , а также artist ,
Если вы хотите отформатировать произвольно большие потоки (xslt использует модель в памяти), вы можете прочитать их в программе чтения событий stax и просто записать их снова, отбрасывая события пробела и вставляя событие новой строки, когда вы встречаете каталог или компакт-диск. событие конечного элемента. Вы даже можете просто удалить этот шаг и игнорировать события cd, которые вас не интересуют при записи результата.
Я хочу сделать это преобразование, потому что я хочу быстро удалить некоторые записи (в данном случае 'cd') из XML-файла. Использование однострочного формата помогло бы мне.
Разве не проще было бы просто удалить нужные "записи" из XML с помощью XSLT? Это было бы проще, чем изменить разрывы / пробелы с помощью XSLT, а затем использовать что-то еще, чтобы удалить то, что вам не нужно. (Что вы планировали использовать? Собирались ли вы удалить все строки, которые начинались с <cd> ?)
В XSLT просто отбросить ненужные данные, если вы используете преобразование идентичности. Вы можете добавить пустой шаблон для всего, что не хотите хранить.
Короче; у меня есть много пустых строк, сгенерированных в XML-файле, и я ищу способ удалить их, как способ наклонить файл. Как я могу это сделать?
Для подробного объяснения; В настоящее время у меня есть этот файл XML:
И я использую этот код Java, чтобы удалить все теги, и вместо этого добавить новые:
После выполнения этого метода несколько раз я получаю файл XML с правильными результатами, но с множеством пустых строк после тега "paths" и перед первым тегом "path", например:
------------------------------------------- Редактировать: добавить getXMLFile(. ), код saveXMLFile(. ).
Это удалит все сгенерированные пустые места в файле XML.
Отдельное спасибо MadProgrammer за комментирование с помощью полезной ссылки, упомянутой выше.
Во-первых, объяснение того, почему это происходит - что может быть немного не так, поскольку вы не включили код, который используется для загрузки файла XML в объект DOM.
Когда вы читаете XML-документ из файла, пробелы между тегами фактически составляют действительные узлы DOM, в соответствии со спецификацией DOM. Поэтому синтаксический анализатор XML обрабатывает каждую такую последовательность пробелов как узлы DOM (типа "TEXT");
Чтобы избавиться от этого, есть три подхода, которые я могу придумать:
Свяжите XML со схемой, а затем используйте setValidating(true) вместе с setIgnoringElementContentWhitespace(true) на DocumentBuilderFactory ,
(Заметка: setIgnoringElementContentWhitespace будет работать только если парсер находится в режиме проверки, поэтому вы должны использовать setValidating(true) )
Для этого используйте код Java: используйте XPath, чтобы найти все узлы TEXT только для пробелов, выполнить итерацию по ним и удалить каждый из своих родительских узлов (используя getParentNode().removeChild() ). Чтобы сделать это в коде Java, что-то вроде этого будет делать ( doc будет вашим объектом документа DOM):
Вы можете посмотреть на что-то вроде этого, если вам нужно только быстро "почистить" ваш xml. Тогда у вас может быть такой метод:
Кроме того, для сравнения различий можно проверить разницу, если она вам нужна: XMLUnit
Я использую ниже код:
Я столкнулся с той же проблемой, и долгое время понятия не имел, но теперь, после вопроса Брэда и его собственного ответа на его собственный вопрос, я понял, в чем проблема.
Я должен добавить свой собственный ответ, потому что ответ Брэда не очень совершенен, как сказал Исаак:
Я не был бы большим поклонником слепого удаления дочерних узлов, не зная, что они
Итак, лучшее "решение" (цитируемое, потому что это более вероятное решение):
Это полностью удаляет ненужные пустые строки. Это определенно лучше, чем удаление всех дочерних узлов. Брэд, это должно сработать и для тебя.
Но это следствие, а не причина, и мы получили, как устранить этот эффект, а не причину.
Причина такова: когда мы звоним removeChild() , он удаляет этот дочерний элемент, но оставляет отступ удаленного дочернего элемента и разрыв строки. И этот indent_and_like_break рассматривается как текстовое содержимое.
Читайте также: