用于选择命名空间属性的XSLT

时间:2009-12-30 08:41:27

标签: xml xslt

放弃PHP后,我试图使用XSLT从xml中提取数据

如何匹配<jskit:attribute key="permalink"

中的数据

我看到了另一个关于名称值对的类似问题,但距离

还有一步之遥

我的xml在这里xml source

3 个答案:

答案 0 :(得分:1)

首先,确保您要使用的所有命名空间在xslt中都可用。例如,在top元素中为所有这些前缀定义xmlns前缀,如下所示:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:jskit="http://purl.org/dc/elements/1.1/"
>
    ... xslt templates go here...
</xsl:stylesheet>

之后,您可以在XPath表达式中使用名称空间前缀jskit。

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:jskit="http://purl.org/dc/elements/1.1/"
>
    <!-- match all items anywhere in the document -->
    <xsl:template match="//item">
         <!-- get the "value" attribute of the "jskit:attribute" element 
              in the current item in case the "key" attribute is called "permalink"
         --> 
         <xsl:value-of select="jskit:attribute[@key='permalink']/@value"/>
         , <!-- comma separator, literal txt -->             
         <!-- get the "value" attribute of the "jskit:attribute" element 
              in the current item in case the "key" attribute is called "IP"
         --> 
         <xsl:value-of select="jskit:attribute[@key='IP']/@value"/>    
    </xsl:template>
</xsl:stylesheet>

您需要编写的模板和XPath完全取决于您所需输出格式的要求,如果我们缺少该信息,则不容易完全回答

但是,假设您要将数据插入数据库,然后可以直接使用XSLT生成SQL语句:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:jskit="http://purl.org/dc/elements/1.1/"
>
    <!-- make text output (SQL script) -->
    <xsl:output
        method="text"
    />

    <!-- match all items anywhere in the document -->
    <xsl:template match="//item">
         INSERT INTO myTable(permalink, IP) VALUES
         ('<xsl:value-of select="jskit:attribute[@key='permalink']/@value"/>'
         ,'<xsl:value-of select="jskit:attribute[@key='IP']/@value"/>');
    </xsl:template>
</xsl:stylesheet>

但是,为了使这种事情非常健壮,您必须确保最终在SQL语句中的值不包含任何字符串分隔符。例如,如果永久链接可能包含单引号,那么这将生成无效的SQL,因为该值的单引号会过早地结束字符串文字SQL值。

为了解决这个问题,您可以编写一个递归处理文本值的模板来逃避那些需要它的字符(除了引用之外,根据您的数据库,您可能还需要转义其他字符)

Anothter方法是使用XSLT将数据转换为您可以使用宿主语言轻松解析的格式。假设您正在使用PHP,那么您可以使用XSLT将XML转换为ini文件格式,使用parse_ini_file()解析它,然后使用PHP正确转义/验证值,然后执行数据库操作。

YMMV

答案 1 :(得分:0)

有问题的节点的Xpath表达式如下:

/rss/channel/item/jskit:attribute[@key='IP']/@value

/rss/channel/item/jskit:attribute[@key='permalink']/@value

/rss/channel/item/jskit:parent-guid

前两个使用谓词来选择具有等于“IP”或“永久链接”的相应键的节点。第三个是选择单个节点的正常表达式。

为了能够使用命名空间访问这些节点,您需要在XSLT中定义命名空间前缀。这是在<xsl:stylesheet>元素中完成的。对于此应用程序,您只需从XML源复制声明即可。

XSLT中的完整示例

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:dc="http://purl.org/dc/elements/1.1/" 
    xmlns:atom="http://www.w3.org/2005/Atom" 
    xmlns:media="http://search.yahoo.com/mrss/" 
    xmlns:jskit="http://purl.org/dc/elements/1.1/"
    exclude-result-prefixes="atom media jskit dc">

    <xsl:template match="/">
        <ip>
            <xsl:value-of 
                select="/rss/channel/item/jskit:attribute[@key='IP']/@value"/>
        </ip>
        <permalink>
            <xsl:value-of 
                select="/rss/channel/item/jskit:attribute[@key='permalink']/@value"/>
        </permalink>
        <parent-guid>
            <xsl:value-of 
                select="/rss/channel/item/jskit:parent-guid"/>
        </parent-guid>
    </xsl:template>
</xsl:stylesheet>

要将样式表附加到XML文件,请使用名为xml-stylesheet

的处理指令
<?xml version="1.0"?>
<?xml-stylesheet href="rss.xsl" type="text/xsl" ?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" 
    xmlns:atom="http://www.w3.org/2005/Atom" 
    xmlns:media="http://search.yahoo.com/mrss/" 
    xmlns:jskit="http://purl.org/dc/elements/1.1/" >

答案 2 :(得分:0)

  

放弃PHP之后,我试图使用XSLT从xml中提取数据

有什么可以放弃的? PHP对XML有很好的支持。您可以使用DomXPath在xml文档中进行查询。首先使用registerNamespace,以便能够查询命名空间属性。例如:

$doc = new DOMDocument();
$doc->loadXML($xml);
$xpath = new DOMXPath($doc);
$xpath->registerNamespace("jskit", "http://purl.org/dc/elements/1.1/");
$query = "//jskit:attribute[@key='permalink']";
foreach ($xpath->evaluate($query) as $node) {
  echo $node, "\n";
}