我需要检查XML节点的属性是否包含其中一个值 这是我的XML:
<manifest>
<item id="item_557c683790288" href="navigation.ncx" media-type="application/x-dtbncx+xml"/>
<item id="toc" href="navigation.xhtml" media-type="application/xhtml+xml" properties="nav"/>
<item id="item_557c68379035d" href="title-page.html" media-type="application/xhtml+xml" properties="scripted"/>
<item id="item_557c683790414" href="imprint.html" media-type="application/xhtml+xml" properties="scripted svg"/>
<item id="item_557c6837904b6" href="author.html" media-type="application/xhtml+xml" properties="scripted"/>
<item id="item_557c683790572" href="file_557c6766c75a9.html" media-type="application/xhtml+xml" properties="scripted"/>
<item id="item_557c683790625" href="liberio.css" media-type="text/css"/>
<item id="item_557c6837906ef" href="assets/2dcc626f-387f-4658-d6f6-58570ae176e7.jpg" media-type="image/jpeg"/>
<item id="item_557c6837907c4" href="assets/liberio_color.svg" media-type="image/svg+xml"/>
<item id="item_557c683790879" href="assets/93d7f25284aeda831bde692e6b002b9f.png" media-type="image/png"/>
<item id="item_557c683790949" href="assets/properties.js" media-type="application/javascript"/>
</manifest>
现在我使用以下表达式:
$images = $this->opfSxml->xpath("//*[local-name()='manifest']/*[local-name()='item'][contains(@media-type,'png') or contains(@media-type, 'jpg') or contains(@media-type, 'ico') ]");
我的代码正在运行,但我正在检查的每个值都重复OR和CONTAINS,对我来说感觉不错。
有没有简短的方法来写这个?
答案 0 :(得分:2)
使用强>:
//manifest/*[contains('png|jpeg|ico',substring-after(@media-type,'/'))]
这假设媒体类型是无前缀的字符串 - 也就是说,没有这样的字符串是另一个字符串的前缀。
如果无前缀假设不成立,请使用:
//manifest/*[contains('|png|jpeg|ico|',concat('|',substring-after(@media-type,'/'),'|'))]
答案 1 :(得分:1)
在纯XPath中 - 没有。 我能想到的最短的XPath是:
//manifest/item[contains(@media-type,'png') or contains(@media-type, 'jpg') or contains(@media-type, 'ico') ]
答案 2 :(得分:0)
我不认为它更短,
$dom = new DOMDocument;
$dom->loadXML($str);
$xp = new DOMXPath($dom);
// Create function returning boolean
function is_image($str) {
str_replace(['png','jpeg','ico'], '', $str, $c);
// If substring found, it returns true
return $c !== 0 ;
}
$xp->registerPHPFunctions();
$xp->registerNamespace("php", "http://php.net/xpath");
// And now our short Xpath :)
$images = $xp->query("//item[php:function('is_image', string(@media-type))]");
foreach($images as $img)
print_r($img);
答案 3 :(得分:-2)
这是我将使用的方法。没有OR。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
string[] media_types = { "png", "jpg", "ico" };
XElement manifest = XElement.Load(FILENAME);
var items = manifest.Descendants("item").Select(x => new
{
id = (string)x.Attribute("item"),
href = (string)x.Attribute("href"),
media = (string)x.Attribute("media-type")
}).ToList();
var media = items.Where(x => media_types.Contains(x.href.Substring(x.href.LastIndexOf(".") + 1))).ToList();
}
}
}