我正试图找到一种方法来清理来自如下html源的一堆空dom元素:
<div class="empty">
<div> </div>
<div></div>
</div>
<a href="http://example.com">good</a>
<div>
<p></p>
</div>
<br>
<img src="http://example.com/logo.png" />
<div></div>
<a href="http://example.com">good</a>
<br>
<img src="http://example.com/logo.png" />
$xpath = new DOMXPath($dom);
//$x = '//*[not(*) and not(normalize-space(.))]';
//$x = '//*[not(text() or node() or self::br)]';
//$x = 'not(normalize-space(.) or self::br)';
$x = '//*[not(text() or node() or self::br)]';
while(($nodeList = $xpath->query($x)) && $nodeList->length > 0) {
foreach ($nodeList as $node) {
$node->parentNode->removeChild($node);
}
}
<div>
<div> </div>
</div>
<a href="http://example.com">good</a>
<div>
</div>
<br>
最佳答案
一、初始溶液:
xpath是xml文档的查询语言。因此,对xpath表达式的求值仅选择节点或从xml文档中提取非节点信息,而从不更改xml文档。因此,对xpath表达式求值从不删除或插入节点——xml文档保持不变。
您想要的是“从html源代码中清除一堆空的dom元素”,而不能只使用xpath。
这一点得到了xpath上最可信、也是唯一官方(我们称之为规范性)的消息来源的证实。
“xpath的主要目的是处理xml[xml]
文件。为了支持这个主要目的,它还提供了
操作字符串、数字和布尔值的工具。XPath
使用紧凑的非xml语法来促进uri中xpath的使用
和XML属性值。xpath对抽象的、逻辑的
XML文档的结构,而不是其表面语法。XPath
从使用路径表示法中获取其名称,如
在XML文档的层次结构中导航。”
因此,为了实现所需的功能,必须将一些附加语言与xpath结合使用。
xslt是一种专门为xml转换而设计的语言。
下面是一个基于xslt的示例——一个执行请求的清理的简短xslt转换:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"*[not(string(translate(., ' ', '')))
and
not(descendant-or-self::*
[self::img or self::input or self::br])]"/>
</xsl:stylesheet>
<html>
<div class="empty">
<div> </div>
<div></div>
</div>
<a href="http://example.com">good</a>
<div>
<p></p>
</div>
<br />
<img src="http://example.com/logo.png" />
<div></div>
</html>
<html>
<a href="http://example.com">good</a>
<br/>
<img src="http://example.com/logo.png"/>
</html>
img,input和br),其字符串值是空字符串,任何 都已从中删除。这个模板的主体是空的,这实际上“删除”了匹配的元素——匹配的元素不会复制到输出中。//*[not(normalize-space((translate(., ' ', ''))))
and
not(descendant-or-self::*[self::img or self::input or self::br])
]
[not(ancestor::*
[count(.| //*[not(normalize-space((translate(., ' ', ''))))
and
not(descendant-or-self::*
[self::img or self::input or self::br])
]
)
=
count(//*[not(normalize-space((translate(., ' ', ''))))
and
not(descendant-or-self::*
[self::img or self::input or self::br])
]
)
]
)
]
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"//*[not(normalize-space((translate(., ' ', ''))))
and
not(descendant-or-self::*[self::img or self::input or self::br])
]
[not(ancestor::*
[count(.| //*[not(normalize-space((translate(., ' ', ''))))
and
not(descendant-or-self::*
[self::img or self::input or self::br])
]
)
=
count(//*[not(normalize-space((translate(., ' ', ''))))
and
not(descendant-or-self::*
[self::img or self::input or self::br])
]
)
]
)
]
"/>
</xsl:stylesheet>
<html>
<a href="http://example.com">good</a>
<br/>
<img src="http://example.com/logo.png"/>
</html>
$vAllEmpty表示“empty”的所有节点。$vAllEmpty用以下xpath表达式表示: //*[not(normalize-space((translate(., ' ', ''))))
and
not(descendant-or-self::*
[self::img or self::input or self::br])
]
$vAllEmpty中删除“top nodes”$vTopEmpty。$vTopEmpty可以使用以下xpath 2.0表达式从$vAllEmpty中表示:$vAllEmpty[not(ancestor::* intersect $vAllEmpty)]
$vAllEmpty中选择那些没有也在$vAllEmpty中的祖先元素的节点。$vAllEmpty[not(ancestor::*[count(.|$vAllEmpty) = count($vAllEmpty)])]
$vAllEmpty替换为上面定义的扩展xpath表达式,这就是我们获取最终表达式的方式,它只选择“要删除的顶部节点”://*[not(normalize-space((translate(., ' ', ''))))
and
not(descendant-or-self::*[self::img or self::input or self::br])
]
[not(ancestor::*
[count(.| //*[not(normalize-space((translate(., ' ', ''))))
and
not(descendant-or-self::*
[self::img or self::input or self::br])
]
)
=
count(//*[not(normalize-space((translate(., ' ', ''))))
and
not(descendant-or-self::*
[self::img or self::input or self::br])
]
)
]
)
]
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vAllEmpty" select=
"//*[not(normalize-space((translate(., ' ', ''))))
and
not(descendant-or-self::*
[self::img or self::input or self::br])
]"/>
<xsl:variable name="vTopEmpty" select=
"$vAllEmpty[not(ancestor::* intersect $vAllEmpty)]"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[. intersect $vTopEmpty]"/>
</xsl:stylesheet>
$vTopEmpty的任何节点除外。结果是正确的和预期的:<html>
<a href="http://example.com">good</a>
<br/>
<img src="http://example.com/logo.png"/>
</html>
//node()
[self::input or self::img or self::br
or
self::text()[normalize-space(translate(.,' ',''))]
]
/ancestor-or-self::node()
//node()
[not(count(.
|
//node()
[self::input or self::img or self::br
or
self::text()[normalize-space(translate(.,' ',''))]
]
/ancestor-or-self::node()
)
=
count(//node()
[self::input or self::img or self::br
or
self::text()[normalize-space(translate(.,' ',''))]
]
/ancestor-or-self::node()
)
)
]
关于php - XPath递归删除空的DOM节点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11744454/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html
我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的
我使用Nokogiri(Rubygem)css搜索寻找某些在我的html里面。看起来Nokogiri的css搜索不喜欢正则表达式。我想切换到Nokogiri的xpath搜索,因为这似乎支持搜索字符串中的正则表达式。如何在xpath搜索中实现下面提到的(伪)css搜索?require'rubygems'require'nokogiri'value=Nokogiri::HTML.parse(ABBlaCD3"HTML_END#my_blockisgivenmy_bl="1"#my_eqcorrespondstothisregexmy_eq="\/[0-9]+\/"#FIXMEThefoll
在Ruby中是否有Gem或安全删除文件的方法?我想避免系统上可能不存在的外部程序。“安全删除”指的是覆盖文件内容。 最佳答案 如果您使用的是*nix,一个很好的方法是使用exec/open3/open4调用shred:`shred-fxuz#{filename}`http://www.gnu.org/s/coreutils/manual/html_node/shred-invocation.html检查这个类似的帖子:Writingafileshredderinpythonorruby?
我正在学习http://ruby.railstutorial.org/chapters/static-pages上的RubyonRails教程并遇到以下错误StaticPagesHomepageshouldhavethecontent'SampleApp'Failure/Error:page.shouldhave_content('SampleApp')Capybara::ElementNotFound:Unabletofindxpath"/html"#(eval):2:in`text'#./spec/requests/static_pages_spec.rb:7:in`(root)'
我正在尝试找到一种方法来规范化字符串以将其作为文件名传递。到目前为止我有这个:my_string.mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n,'').downcase.gsub(/[^a-z]/,'_')但第一个问题:-字符。我猜这个方法还有更多问题。我不控制名称,名称字符串可以有重音符、空格和特殊字符。我想删除所有这些,用相应的字母('é'=>'e')替换重音符号,并将其余的替换为'_'字符。名字是这样的:“Prélèvements-常规”“健康证”...我希望它们像一个没有空格/特殊字符的文件名:“prelevements_routin
我去了这个website查看Rails5.0.0和Rails5.1.1之间的区别为什么5.1.1不再包含:config/initializers/session_store.rb?谢谢 最佳答案 这是删除它的提交:Setupdefaultsessionstoreinternally,nolongerthroughanapplicationinitializer总而言之,新应用没有该初始化器,session存储默认设置为cookie存储。即与在该初始值设定项的生成版本中指定的值相同。 关于
啊,正则表达式有点困惑。我正在尝试删除字符串末尾所有可能的标点符号:ifstr[str.length-1]=='?'||str[str.length-1]=='.'||str[str.length-1]=='!'orstr[str.length-1]==','||str[str.length-1]==';'str.chomp!end我相信有更好的方法来做到这一点。有什么指点吗? 最佳答案 str.sub!(/[?.!,;]?$/,'')[?.!,;]-字符类。匹配这5个字符中的任何一个(注意,。在字符类中并不特殊)?-前一个字符或组