xml - 使用 XPath 获取/记录上下文节点的子节点

标签 xml xslt xpath

关于 another thread关于使用 XSLT 列出 XML 文件中的每个节点,Alejandro 提供了 this useful piece of XPath 2.0 code:

编辑:我下面的样式表现在使用 Alejandro 在评论中贴出的代码的修改版本。它报告元素的@name 属性。

我对它进行了大量修改以适用于 .xsd 架构,如下所示:

示例模式

(此 source 的简化版本)

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:annotation>
    <xsd:documentation xml:lang="en">
 Purchase order schema for Example.com.
 Copyright 2000 Example.com. All rights reserved.
</xsd:documentation>
</xsd:annotation>
<xsd:element name="comment" type="xsd:string">
    <xsd:annotation>
        <xsd:documentation>doc for comment</xsd:documentation>
    </xsd:annotation>
</xsd:element>
<xsd:complexType name="USAddress">
    <xsd:annotation>
        <xsd:documentation>doc for USAddress</xsd:documentation>
    </xsd:annotation>
    <xsd:sequence>
        <xsd:element name="name" type="xsd:string"/>
        <xsd:element name="street" type="xsd:string"/>
        <xsd:element name="city" type="xsd:string"/>
        <xsd:element name="state" type="xsd:string"/>
        <xsd:element name="zip" type="xsd:decimal"/>
    </xsd:sequence>
    <xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/>
</xsd:complexType>
<!-- Stock Keeping Unit, a code for identifying products -->
<xsd:simpleType name="SKU">
    <xsd:annotation>
        <xsd:documentation>doc for SKU</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
        <xsd:pattern value="\d{3}-[A-Z]{2}"/>
    </xsd:restriction>
</xsd:simpleType>
</xsd:schema>
我的 XSLT 样式表:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsl:template match="*|@*">
<xsl:value-of select="
string-join(
distinct-values(
(//*|//@*)
/string-join(
(ancestor::node()/name(),
if (self::attribute())
    then concat('@',name())
    else if (self::*[@name]) 
        then concat(name(),'[@name=&quot;',@name,'&quot;]')
        else name()),
'/')),
'&#xA;')
"/>
    </xsl:template>
    </xsl:stylesheet>
结果:
/xsd:schema
/xsd:schema/xsd:annotation
/xsd:schema/xsd:annotation/xsd:documentation
/xsd:schema/xsd:annotation/xsd:documentation/@xml:lang
/xsd:schema/xsd:element[@name="comment"]
/xsd:schema/xsd:element/@name
/xsd:schema/xsd:element/@type
/xsd:schema/xsd:element/xsd:annotation
/xsd:schema/xsd:element/xsd:annotation/xsd:documentation
/xsd:schema/xsd:complexType[@name="USAddress"]
/xsd:schema/xsd:complexType/@name
/xsd:schema/xsd:complexType/xsd:annotation
/xsd:schema/xsd:complexType/xsd:annotation/xsd:documentation
/xsd:schema/xsd:complexType/xsd:sequence
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element[@name="name"]
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element/@name
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element/@type
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element[@name="street"]
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element[@name="city"]
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element[@name="state"]
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element[@name="zip"]
/xsd:schema/xsd:complexType/xsd:attribute[@name="country"]
/xsd:schema/xsd:complexType/xsd:attribute/@name
/xsd:schema/xsd:complexType/xsd:attribute/@type
/xsd:schema/xsd:complexType/xsd:attribute/@fixed
/xsd:schema/xsd:simpleType[@name="SKU"]
/xsd:schema/xsd:simpleType/@name
/xsd:schema/xsd:simpleType/xsd:annotation
/xsd:schema/xsd:simpleType/xsd:annotation/xsd:documentation
/xsd:schema/xsd:simpleType/xsd:restriction
/xsd:schema/xsd:simpleType/xsd:restriction/@base
/xsd:schema/xsd:simpleType/xsd:restriction/xsd:pattern
/xsd:schema/xsd:simpleType/xsd:restriction/xsd:pattern/@value

就这个问题而言,这个输出很好。

现在,而不是问“我的代码有什么问题?”我只想问从实际有效的基本状态开始的最佳方法。

我需要添加一个子句,对于带有 /xsd:documentation 的每一行孙子,附加来自 <xsd:documentation>foo</xsd:documentation> 的文本.所以这一行:

/xsd:schema/xsd:element[@name="comment"]

变成:

/xsd:schema/xsd:element[@name="comment"] | doc for comment

谢谢, 马特

最佳答案

解决方法很简单:

.1。在样式表中定义 xsd 命名空间:

<xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
>

.2。变化:

.//documentation

.//xsd:documentation

顺便说一句,这是错误的:

//xsd|//@*

文档中没有名为xsd 的元素。可能你想要:

//xsd:*|//@* 

此外,不需要在属性上使用local-name(),只需name()即可。

第二次观察:

Alejandro 的解决方案没有任何问题。应用于提供的 XML 文档,它会产生以下正确的输出:

/xsd:schema
/xsd:schema/xsd:annotation
/xsd:schema/xsd:annotation/xsd:documentation
/xsd:schema/xsd:annotation/xsd:documentation/@xml:lang
/xsd:schema/xsd:element
/xsd:schema/xsd:element/@name
/xsd:schema/xsd:element/@type
/xsd:schema/xsd:element/xsd:annotation
/xsd:schema/xsd:element/xsd:annotation/xsd:documentation
/xsd:schema/xsd:complexType
/xsd:schema/xsd:complexType/@name
/xsd:schema/xsd:complexType/xsd:sequence
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element/@name
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element/@type
/xsd:schema/xsd:complexType/xsd:attribute
/xsd:schema/xsd:complexType/xsd:attribute/@name
/xsd:schema/xsd:complexType/xsd:attribute/@type
/xsd:schema/xsd:complexType/xsd:attribute/@fixed
/xsd:schema/xsd:complexType/xsd:annotation
/xsd:schema/xsd:complexType/xsd:annotation/xsd:documentation
/xsd:schema/xsd:simpleType
/xsd:schema/xsd:simpleType/@name
/xsd:schema/xsd:simpleType/xsd:restriction
/xsd:schema/xsd:simpleType/xsd:restriction/@base
/xsd:schema/xsd:simpleType/xsd:restriction/xsd:pattern
/xsd:schema/xsd:simpleType/xsd:restriction/xsd:pattern/@value
/xsd:schema/xsd:simpleType/xsd:annotation
/xsd:schema/xsd:simpleType/xsd:annotation/xsd:documentation

关于xml - 使用 XPath 获取/记录上下文节点的子节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4949811/

相关文章:

python - 如何在 python 中抓取网页上的嵌入式脚本

python - 为什么selenium找不到标签和类

Java:解析可能不存在的XML子元素

xml - 在 XSLT 中递归组合相同的兄弟元素

xml - 选择多变量 XSL 中的第一个节点

java - 如何使用 Java 或 XSLT 删除空 XML 节点

xml - 使用 Relax NG 允许附加属性

c++ - 使用 CComPtr<IXMLDOMDocument> (C++) 保存 xml header

xml - 如何使用 linux 命令(示例 sed)删除 xml 文件中的属性

java - Solr 管理员给出 404 错误