XSLT - 使用动态 ID 查询其他节点上的信息

XSLT - work with dynamic id to query information on other node

我被卡住了一段时间,请问您能给我一些建议吗?

我有一个很大的XML,它是由一个软件生成的。它包含以下数据

我想使用 hasNote/list/ref 节点上的 ID 来使用该 ID 显示 Note 节点上的信息。 hasnote/list/ref中的id确实对应我要在Note节点中访问的id。

我是 XSLT 的新手,所以我编译了类似的东西 XSLT

<?xml version="1.0" encoding="UTF-8" ?>

<xsl:stylesheet version="2.0" exclude-result-prefixes="xs xdt err fn" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:fn="http://www.w3.org/2005/xpath-functions" 
    xmlns:xdt="http://www.w3.org/2005/xpath-datatypes"
    xmlns:err="http://www.w3.org/2005/xqt-errors">
<xsl:output method="text" indent="no" omit-xml-declaration="yes"/>
<xsl:template match="/archive">
<xsl:text>"Name","Description","RuleType","Active","Threshold","ID","VersionID","Alias","#childOf","#dependantOf","#hasDependant","Owner/Author","Misc","Notes"</xsl:text>
<xsl:variable name="quote">"</xsl:variable>
<xsl:variable name="apos">'</xsl:variable>

<xsl:for-each select="child::*">
            <xsl:choose>
                <xsl:when test="name(.) = 'Rule'">
"<xsl:value-of select="@name"/>","<xsl:value-of select="description"/>","<xsl:if test="contains(replace(./def/text(),$quote,''), 'Type=Normal ID=')">Normal</xsl:if><xsl:if test="contains(replace(./def/text(),$quote,''), 'Type=Lightweight ID=')">Lightweight</xsl:if><xsl:if test="contains(replace(./def/text(),$quote,''), 'Type=Prepersist ID=')">Prepersist</xsl:if>",<xsl:if test="active='0'">"NO-A"</xsl:if><xsl:if test="active='1'">"YES"</xsl:if><xsl:if test="active='2'">"NO"</xsl:if>,"<xsl:value-of select="concat(replace(replace(replace(replace(replace(substring-before(substring-after(./def/text(),'Threshold='),'Condition ConditionType='),'&#xA;',''),'&lt;',''),'&gt;',''),$quote,''),'^\s+|\s+$', ''),' in ',replace(replace(concat(substring-before(substring-after(./def/text(),'TimeWindowSize='),' TimeUnit='),substring-before(substring-after(./def/text(),'TimeUnit='),' Threshold=')),$quote,' '),'^\s+|\s+$', ''))"/>","<xsl:value-of select="@id"/>","<xsl:value-of select="@versionID"/>","","<xsl:value-of select="count(childOf/list/ref)"/>","<xsl:value-of select="count(dependantOf/list/ref)"/>","","","<xsl:value-of select="replace(replace(./def/text(), $quote, $apos),'&#xA;','.')" disable-output-escaping="no"/>","<xsl:for-each select="hasNote/list/ref"><xsl:value-of select="@id"/><xsl:attribute name="id"><xsl:value-of select="Note/@id" /></xsl:attribute></xsl:for-each>"</xsl:when>
</xsl:choose></xsl:for-each>

</xsl:template>
</xsl:stylesheet>

期望的输出,应该以我的 CSV 输出格式显示来自 Note 的信息。

Name, Description, RuleType, Active, Threshold, ID, Version ID, ALias, Childof, Depandatof, hasdependant, owner/author, Misc, **Note**
Rules1, Used to manage user, Normal, Yes, 1 in 2 minutes, 1.0,-,-,-,-,Myself, Additional information , My note lalalala | RENOTE gdfgdfgdfgfd

其中 Note 是来自 Note/data 的数据,在我的示例中:My note lalalala

我尝试使用那部分代码访问笔记信息,但它不起作用

"<xsl:for-each select="hasNote/list/ref"><xsl:value-of select="@id"/><xsl:attribute name="id"><xsl:value-of select="Note/@id" /></xsl:attribute></xsl:for-each>"

XML:

       <Note id="85EVs5EsBABCAem1CaU3lEQ==" name="85EVs5EsBABCAem1CaU3lEQ==" action="insert" >
      <author>admin</author>
      <childOf>
         <list>
            <ref type="Group" uri="/All Notes/" id="01000100010001008"/>
         </list>
      </childOf>
      <createTime>1425466476004</createTime>
      <data>My note lalalala</data>
      <noteOf>
         <list>
            <ref type="Rule" uri="/All Rules/" id="5-I5qOkoBABCj2Yy+wpORuA=="/>
         </list>
      </noteOf>
   </Note>
   <Note id="8D5ds5EsBABCAfGc3-q2h+Q==" name="8D5ds5EsBABCAfGc3-q2h+Q==" action="insert" >
      <author>admin</author>
      <childOf>
         <list>
            <ref type="Group" uri="/All Notes/" id="01000100010001008"/>
         </list>
      </childOf>
      <createTime>1425466496783</createTime>
      <data>RENOTE gdfgdfgdfgfd</data>
      <noteOf>
         <list>
            <ref type="Rule" uri="/All Rules/" id="5-I5qOkoBABCj2Yy+wpORuA=="/>
         </list>
      </noteOf>
   </Note>
<Rule id="5l+jzGUoBABChieXrzh1TVQ==" name="ruleexemple" versionID="V1.0" action="insert" >
<active>1</active>
      <childOf>
         <list>
            <ref type="Group" uri="/All Rules" id="0S7GEnUEBABCGDB3i0QUfrw=="/>
         </list>
      </childOf>

<def><![CDATA[<Rule Name="ruleexemple" Type="Normal" ID="5-I5qOkoBABCj2Yy+wpORuA==">
  <Description>My Own Description</Description>
  <Query>
    <FromClause>
      <Table Name="Event" Alias="event1" AliasType="Positive" />
    </FromClause>
    <WhereClause TimeWindowSize="2" TimeUnit="Minute" Threshold="1">
      <Condition ConditionType="Positive" TableAlias="event1">
      </Condition>

</Rule>]]></def>
      <dependantOf>
         <list>
            <ref type="List" uri="/All Lists/" id="H47NgOkoBABDBEBnyq05r8g=="/>
            <ref type="List" uri="/All Lists" id="HaVFbOkoBABCjACrgyZldRw=="/>
         </list>
      </dependantOf>
      <description>My Own Description</description>
      <hasNote>
         <list>
            <ref type="Note" uri="/All Notes/85EVs5EsBABCAem1CaU3lEQ==" id="85EVs5EsBABCAem1CaU3lEQ=="/>
            <ref type="Note" uri="/All Notes/8D5ds5EsBABCAfGc3-q2h+Q==" id="8D5ds5EsBABCAfGc3-q2h+Q=="/>
         </list>
      </hasNote>
</Rule>

<xsl:for-each> 中,上下文节点被移动到 XPath 表达式中的选定元素。

要检索您想要的信息,您应该使用以下方法:

<xsl:for-each select="hasNote/list/ref">
  <xsl:variable name="current.id">
    <xsl:value-of select="@id"/>
  </xsl:variable>

  <xsl:value-of select="//Note[@id = $current.id]/data" />
</xsl:for-each>

正如您提到的,如果您的 XML 确实很大,使用 <xsl:key> 以更有效的方式获取 <Note> 可能是个好主意。

基于 potame 的回答。

我已经像这样扩展了 xslt

  <xsl:for-each select="hasNote/list/ref">
     <xsl:variable name="current.id">
       <xsl:value-of select="@id"/>
     </xsl:variable>
     created by: 
     <xsl:value-of select="//Note[@id = $current.id]/author" />
      on 
     <xsl:value-of select="//Note[@id = $current.id]/createTime" />
      With comment: 
     <xsl:value-of select="//Note[@id = $current.id]/data" />
      |
  </xsl:for-each>

现在我将尝试将 createTime 的值(Unix 时间戳格式)转换为人类可读的格式。

我认为 xsl 有一些功能。不是吗?