XML 正在解析破碎的文本
XML Parsing Broken-up Text
我正在寻找解析 word 文档 XML 以获取每个段落、句子或短语的页脚信息。
此命令获取所有文本之间没有空格。
pry(main)> doc.header_and_footers_xml[1].text()
=> " PAGE 1FirstGoogle.comSomething privacy Saturday, February 23, 2019"
这个命令稍微好一点,但是以奇怪的方式分解了文本:
pry(main)> doc.header_and_footers_xml[1].search('//text()')
=> [#<Nokogiri::XML::Text:0x3fdf0eb0c3a4 " PAGE ">, #<Nokogiri::XML::Text:0x3fdf10c41b78 "1">, #<Nokogiri::XML::Text:0x3fdf0eaa427c "F">, #<Nokogiri::XML::Text:0x3fdf0ea60bbc "irst">, #<Nokogiri::XML::Text:0x3fdf0e9f9bc4 "Google.com">, #<Nokogiri::XML::Text:0x3fdf0f6b636c "Something privacy">, #<Nokogiri::XML::Text:0x3fdf0b9ded90 " Saturday, February 23, 2019">]
pry(main)> doc.header_and_footers_xml[1].search('//text()')[2]
=> #(Text "F")
pry(main)> doc.header_and_footers_xml[1].search('//text()')[3]
=> #(Text "irst")
我想接收迭代 list/array 的元素:'PAGE'、'1'、'First'、'Google.com'、'Something privacy'、'Saturday, February 23, 2019'
下面是完整的XML。是否可以只迭代 name = "p"
个元素?
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:hdr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:sdt>
<w:sdtPr>
<w:rPr>
<w:rStyle w:val="PageNumber" />
</w:rPr>
<w:id w:val="-157074914" />
<w:docPartObj>
<w:docPartGallery w:val="Page Numbers (Top of Page)" />
<w:docPartUnique />
</w:docPartObj>
</w:sdtPr>
<w:sdtEndPr>
<w:rPr>
<w:rStyle w:val="PageNumber" />
</w:rPr>
</w:sdtEndPr>
<w:sdtContent>
<w:p w:rsidR="00140C14" w:rsidRDefault="00140C14" w:rsidP="00AD16D8">
<w:pPr>
<w:pStyle w:val="Header" />
<w:framePr w:wrap="none" w:vAnchor="text" w:hAnchor="margin" w:xAlign="right" w:y="1" />
<w:rPr>
<w:rStyle w:val="PageNumber" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rStyle w:val="PageNumber" />
</w:rPr>
<w:fldChar w:fldCharType="begin" />
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="PageNumber" />
</w:rPr>
<w:instrText xml:space="preserve"> PAGE </w:instrText>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="PageNumber" />
</w:rPr>
<w:fldChar w:fldCharType="separate" />
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="PageNumber" />
<w:noProof />
</w:rPr>
<w:t>1</w:t>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="PageNumber" />
</w:rPr>
<w:fldChar w:fldCharType="end" />
</w:r>
</w:p>
</w:sdtContent>
</w:sdt>
<w:p w:rsidR="002132D5" w:rsidRDefault="00140C14" w:rsidP="00140C14">
<w:pPr>
<w:pStyle w:val="Header" />
<w:ind w:right="360" />
</w:pPr>
<w:r>
<w:t>F</w:t>
</w:r>
<w:r w:rsidR="002132D5">
<w:t>irst</w:t>
</w:r>
</w:p>
<w:p w:rsidR="00140C14" w:rsidRDefault="00140C14" w:rsidP="00140C14">
<w:pPr>
<w:pStyle w:val="Header" />
<w:ind w:right="360" />
</w:pPr>
<w:r>
<w:t>Google.com</w:t>
</w:r>
</w:p>
<w:p w:rsidR="00140C14" w:rsidRDefault="00140C14" w:rsidP="00140C14">
<w:pPr>
<w:pStyle w:val="Header" />
<w:ind w:right="360" />
</w:pPr>
<w:r>
<w:t>Something privacy</w:t>
</w:r>
<w:r w:rsidR="00710468">
<w:t xml:space="preserve"> Saturday, February 23, 2019</w:t>
</w:r>
<w:bookmarkStart w:id="0" w:name="_GoBack" />
<w:bookmarkEnd w:id="0" />
</w:p>
</w:hdr>
这是word文档:
原理是这样的:
- 定义名称空间 URI,以便我们可以使用 XPath 正确搜索
<w:p>
元素。在这种情况下,只有 w:
命名空间是相关的。
- 迭代
<w:p>
个节点
- 加入每个非空文本节点
这可能非常不合惯用语 Ruby,但它应该可以帮助您入门:
require 'nokogiri'
header_and_footers_xml = Nokogiri::XML(open("footer.xml"))
namespaces = {
"w" => "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
}
paras = header_and_footers_xml.search('//w:p', namespaces)
paras.each do |p|
nodes = p.xpath('.//text()[normalize-space()]')
texts = nodes.map { |n| n.text }
puts(texts.join)
end
这会打印 (tested on Ruby 2.5):
PAGE 1
First
Google.com
Something privacy Saturday, February 23, 2019
XPath表达式.//text()[normalize-space()]
收集当前节点(.
)的所有文本节点(text()
)后代,并通过调用normalize-space()
过滤掉空白节点它们中的每一个都去除了空白 - 仅返回那些节点,其中在修剪后保留非空字符串。
我正在寻找解析 word 文档 XML 以获取每个段落、句子或短语的页脚信息。
此命令获取所有文本之间没有空格。
pry(main)> doc.header_and_footers_xml[1].text()
=> " PAGE 1FirstGoogle.comSomething privacy Saturday, February 23, 2019"
这个命令稍微好一点,但是以奇怪的方式分解了文本:
pry(main)> doc.header_and_footers_xml[1].search('//text()')
=> [#<Nokogiri::XML::Text:0x3fdf0eb0c3a4 " PAGE ">, #<Nokogiri::XML::Text:0x3fdf10c41b78 "1">, #<Nokogiri::XML::Text:0x3fdf0eaa427c "F">, #<Nokogiri::XML::Text:0x3fdf0ea60bbc "irst">, #<Nokogiri::XML::Text:0x3fdf0e9f9bc4 "Google.com">, #<Nokogiri::XML::Text:0x3fdf0f6b636c "Something privacy">, #<Nokogiri::XML::Text:0x3fdf0b9ded90 " Saturday, February 23, 2019">]
pry(main)> doc.header_and_footers_xml[1].search('//text()')[2]
=> #(Text "F")
pry(main)> doc.header_and_footers_xml[1].search('//text()')[3]
=> #(Text "irst")
我想接收迭代 list/array 的元素:'PAGE'、'1'、'First'、'Google.com'、'Something privacy'、'Saturday, February 23, 2019'
下面是完整的XML。是否可以只迭代 name = "p"
个元素?
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:hdr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:sdt>
<w:sdtPr>
<w:rPr>
<w:rStyle w:val="PageNumber" />
</w:rPr>
<w:id w:val="-157074914" />
<w:docPartObj>
<w:docPartGallery w:val="Page Numbers (Top of Page)" />
<w:docPartUnique />
</w:docPartObj>
</w:sdtPr>
<w:sdtEndPr>
<w:rPr>
<w:rStyle w:val="PageNumber" />
</w:rPr>
</w:sdtEndPr>
<w:sdtContent>
<w:p w:rsidR="00140C14" w:rsidRDefault="00140C14" w:rsidP="00AD16D8">
<w:pPr>
<w:pStyle w:val="Header" />
<w:framePr w:wrap="none" w:vAnchor="text" w:hAnchor="margin" w:xAlign="right" w:y="1" />
<w:rPr>
<w:rStyle w:val="PageNumber" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rStyle w:val="PageNumber" />
</w:rPr>
<w:fldChar w:fldCharType="begin" />
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="PageNumber" />
</w:rPr>
<w:instrText xml:space="preserve"> PAGE </w:instrText>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="PageNumber" />
</w:rPr>
<w:fldChar w:fldCharType="separate" />
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="PageNumber" />
<w:noProof />
</w:rPr>
<w:t>1</w:t>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="PageNumber" />
</w:rPr>
<w:fldChar w:fldCharType="end" />
</w:r>
</w:p>
</w:sdtContent>
</w:sdt>
<w:p w:rsidR="002132D5" w:rsidRDefault="00140C14" w:rsidP="00140C14">
<w:pPr>
<w:pStyle w:val="Header" />
<w:ind w:right="360" />
</w:pPr>
<w:r>
<w:t>F</w:t>
</w:r>
<w:r w:rsidR="002132D5">
<w:t>irst</w:t>
</w:r>
</w:p>
<w:p w:rsidR="00140C14" w:rsidRDefault="00140C14" w:rsidP="00140C14">
<w:pPr>
<w:pStyle w:val="Header" />
<w:ind w:right="360" />
</w:pPr>
<w:r>
<w:t>Google.com</w:t>
</w:r>
</w:p>
<w:p w:rsidR="00140C14" w:rsidRDefault="00140C14" w:rsidP="00140C14">
<w:pPr>
<w:pStyle w:val="Header" />
<w:ind w:right="360" />
</w:pPr>
<w:r>
<w:t>Something privacy</w:t>
</w:r>
<w:r w:rsidR="00710468">
<w:t xml:space="preserve"> Saturday, February 23, 2019</w:t>
</w:r>
<w:bookmarkStart w:id="0" w:name="_GoBack" />
<w:bookmarkEnd w:id="0" />
</w:p>
</w:hdr>
这是word文档:
原理是这样的:
- 定义名称空间 URI,以便我们可以使用 XPath 正确搜索
<w:p>
元素。在这种情况下,只有w:
命名空间是相关的。 - 迭代
<w:p>
个节点 - 加入每个非空文本节点
这可能非常不合惯用语 Ruby,但它应该可以帮助您入门:
require 'nokogiri'
header_and_footers_xml = Nokogiri::XML(open("footer.xml"))
namespaces = {
"w" => "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
}
paras = header_and_footers_xml.search('//w:p', namespaces)
paras.each do |p|
nodes = p.xpath('.//text()[normalize-space()]')
texts = nodes.map { |n| n.text }
puts(texts.join)
end
这会打印 (tested on Ruby 2.5):
PAGE 1 First Google.com Something privacy Saturday, February 23, 2019
XPath表达式.//text()[normalize-space()]
收集当前节点(.
)的所有文本节点(text()
)后代,并通过调用normalize-space()
过滤掉空白节点它们中的每一个都去除了空白 - 仅返回那些节点,其中在修剪后保留非空字符串。